Can I new[], then cast the pointer, then delete[] safely with built-in types in C++?

c++, memory-management, undefined-behavior, visual-c++

Solution

My initial thought was that it is undefined behavior.

5.3.5/3: "In the second alternative (delete array) if the dynamic type of the object to be deleted differs from its static type, the behavior is undefined.73).

Footnote 73 reads, "This implies that an object cannot be deleted using a pointer of type `void*` because there are no objects of type `void`".

Arguably the object in your example doesn't have a dynamic type, since the definition of "dynamic type" at 1.3.3 mentions "most derived object", and the definition of "most derived object" at 1.8/4 is talking about objects of class type. So I kept looking:

5.2.10/3: "[reinterpret_cast] might, or might not, produce a representation different from the original value"

5.3.5/2: "The value of the operand of `delete` shall be the pointer value which resulted from a previous array new-expression".

I'm not sure whether a reinterpret_cast results in the same pointer value as was input, or not. Possibly it's cleared up by some other bit of the standard which I haven't found yet. I would not call this code "OK" without finding something to definitively state that if you reinterpret_cast a pointer, the result is the same "pointer value" as before, so that by passing it to delete[] you are passing "the pointer value" from new[].

5.2.10/7: "Except that casting [between certain pointer types] and back to its original type yields the original pointer value, the result of such a pointer conversion is unspecified".

This looks like bad news to me - it conspicuously doesn't say that the cast yields the same value, only that the pair of casts over and back, yields the same value. This suggests to me that the single cast is allowed to yield a different value, but it is only suggestive, not explicit. This is the usual problem with the rule that "if the standard doesn't state the behavior, then the behavior is undefined". Just because it doesn't state it in any of the paragraphs I can find using the index, doesn't mean it doesn't state it somewhere else...

We know that in practice we can cast things to unsigned char* in order to inspect their bytes, or void* to copy PODs using memcpy, so there must be some casts guaranteed to create aliases. You might think that if your implementation does create aliases with certain casts, then you're passing in the "same value" you got from new[]. But I'm still not sure that's good enough for delete[]. I think I'm missing something important.

Problem

In my code I have effectively the following: ``` wchar_t* buffer = new wchar_t[size]; // bonus irrelevant code here delete[] reinterpret_cast<char*>( buffer ); ``` Types in question are all built-in and so they have trivial destructors. In VC++ the code above works allright - `new[]` just allocates memory, then `delete[]` just frees it. Is it acceptable in C++? Is it undefined behaviour?

Original source