I apologize if I miss an important point that is somehow implicit in the question and I don't see it. But, regarding this central line:
std::auto_ptr<Base> p(new((void*)(new char[size])) Packet());
This is what I think can be said about it:
The constructor call at the end should be Packet
, not Packet()
, although in practice the compiler might accept it as is, and it might not make any difference
The inner allocation new char[size]
uses the array allocator new []
. The CPP reference states about the expression new [array_n]
:
Note that more than size_of( type ) * array_n might be allocated because of additional information encoded by the compiler (such as the size of the array, since this information is needed in order to destruct the objects in the array properly).
Now, the outer allocator call, new ((void*)(...))
, is an instance of placement new, which is described here as follows:
void* operator new ( std::size_t, void* ptr );
does nothing, returns ptr.
In other words, it may happen that the call to new []
causes the compiler to allocate more memory than strictly required by the array and to encode size-related information in the extra space. However, since placement new does "nothing", it does not handle in any way or remove the extra information.
But, since the use of std::auto_ptr
implies that that deallocation will be carried out using delete
(and not delete []
), the extra information will not be properly deallocated, hence a memory leak or worse may result.
Edit: To avoid relying on the CPP reference only, the relevant parts of the C++ Standard N3337 are as follows:
- § 18.6.1.2 states that only
delete
shall be used to deallocate space allocated by new
, and correspondingly delete []
for space allocated by new []
- § 18.6.1.3 explicitly states that the placement forms of
new
and new []
do not perform any action. This implies that neither can be used to "transform" single-object space into array space.
Now perhaps the real question is whether the application of placement new proposed in the question would be valid if only delete []
was used to deallocate the space later. Perhaps the answer is undefined (which should be interpreted as equivalent to a "No").