I don't think you're right. Even the strictest of strict aliasing rules would only count when the memory is actually allocated for a purpose. Once an allocated block has been released back to the heap with free
, there should be no references to it and it can be given out again by malloc
.
And the void*
returned by malloc
is not subject to the strict aliasing rule since the standard explicitly states that a void pointer can be cast into any other sort of pointer (and back again). C99 section 7.20.3 states:
The pointer returned if the allocation succeeds is suitably aligned so that it may be assigned to a pointer to any type of object and then used to access such an object or an array of such objects in the space allocated (until the space is explicitly deallocated).
In terms of your update (the example) where you don't actually return the memory back to the heap, I think your confusion arises because allocated object are treated specially. If you refer to 6.5/6
of C99, you see:
The effective type of an object for an access to its stored value is the declared type of the object, if any (footnote 75: Allocated objects have no declared type).
Re-read that footnote, it's important.
If a value is stored into an object having no declared type through an lvalue having a type that is not a character type, then the type of the lvalue becomes the effective type of the object for that access and for subsequent accesses that do not modify the stored value.
If a value is copied into an object having no declared type using memcpy or memmove, or is copied as an array of character type, then the effective type of the modified object for that access and for subsequent accesses that do not modify the value is the effective type of the object from which the value is copied, if it has one.
For all other accesses to an object having no declared type, the effective type of the object is simply the type of the lvalue used for the access.
In other words, the allocated block contents will become the type of the data item that you put in there.
If you put a float
in there, you should only access it as a float
(or compatible type). If you put in an int
, you should only process it as an int
(or compatible type).
The one thing you shouldn't do is to put a specific type of variable into that memory and then try to treat it as a different type - one reason for this being that objects are allowed to have trap representations (which cause undefined behaviour) and these representations may occur due to treating the same object as different types.
So, if you were to store an int
in there before the deallocation in your code, then reallocate it as a float
pointer, you should not try to use the float until you've actually put one in there. Up until that point, the type of the allocated is not yet float
.
free
has a monopoly on "deallocating", then that meansfree
is very special. The code in the question does not callfree
, therefore this special behaviour is not available. Therefore, the question is: does "deallocation" occur in the questioner's code - i.e. is the "pseudo-deallocation" in the questioner's code sufficient to bring the object lifetime to an end and to allow a new type to be written to the existing location? – Nathanielnathanilfree()
should have a monopoly on such behavior is particularly absurd on freestanding implementations which aren't required to support that function. – Sharasharaifree
(delete
for C++) monopoly seems relatively new. It is a very silly idea that was never floated in these committees before. – Parachute