Hi All!

I'm having this really nasty problem regarding placement new and delete; more specific: with cleaning up the memory when an exception is thrown in the constructor of a class.

Here's a test class declaring it's own placement new and delete versions:
Qt Code:
  1. class memtest
  2. {
  3. public:
  4. //non-placement overloads omitted
  5. static void* operator new( size_t, void* p )
  6. { return p; }
  7. static void operator delete( void* p, void* )
  8. { ( (memtest*) p )->~memtest(); free( p ); }
  9. static void* operator new [] ( size_t, void* p )
  10. { return p; }
  11. static void operator delete [] ( void* p, void* )
  12. { /* and now ? */ }
  13.  
  14. memtest() :
  15. a( new int )
  16. {
  17. throw( 0 );
  18. }
  19.  
  20. ~memtest()
  21. {
  22. delete a;
  23. }
  24. };
To copy to clipboard, switch view to plain text mode 

Now, working with single objects is no big problem, as the compiler generates code to call the corresponding placement delete when the exception is thrown:

Qt Code:
  1. int main()
  2. {
  3. try
  4. {
  5. memtest* pMem = (memtest*) malloc( sizeof( memtest ) ); //allocate mem
  6. new( pMem ) memtest; //calls placement new and new handler
  7. delete pMem; //won't be reached due to constructor failure
  8. }
  9. catch(...)
  10. {
  11. //no mem leak, compiler generated code called memtest::operator delete( void* p, void* )
  12. }
  13. }
To copy to clipboard, switch view to plain text mode 

The problem arises when using placement new [] and delete []: the compiler will also correctly generate code to call operator delete [] ( void*, void* ), but what am I supposed to put in there?

Qt Code:
  1. int main()
  2. {
  3. try
  4. {
  5. memtest* pMem = (memtest*) malloc( sizeof( memtest ) * 2 + sizeof( size_t ) ); //allocate mem
  6. pMem = new( pMem ) memtest[ 2 ]; //calls placement new[] and iterates it with new handler
  7. delete [] pMem; //won't be reached
  8. }
  9. catch(...)
  10. {
  11. //memleak or crash ??
  12. }
  13. }
To copy to clipboard, switch view to plain text mode 

If I would use

Qt Code:
  1. operator delete [] ( void* p, void* )
  2. {
  3. free( p );
  4. }
To copy to clipboard, switch view to plain text mode 

it will free the allocated memory, but memtest's destructor won't get called, resulting in memtest::a leaking.

If I'd put something like this:

Qt Code:
  1. operator delete [] ( void* p, void* )
  2. {
  3. size_t* pSecretSize = ((size_t*) p) - 1; //new [] stores size in front of array
  4. for( size_t i = 0 ; i < *pSecretSize ; ++i )
  5. (&(mem)[i])->~memtest(); //call destructor
  6. free( pSecretSize ) ; //free
  7. }
To copy to clipboard, switch view to plain text mode 

then it will call the destructor for all elements in the array, and afterwards nicely free the memory.
However, when this gets called from within the constructor, there are two problems:
- at first, p will still point to the beginning of the array memory, not to the beginning of the array, so the pSecretSize stuff is completely wrong
- second, even if the pointer passed pointed to the beginning of the array, the code crashes the program since it calls destructors of objects that are not constructed.

Am I missing something, or is it just impossible to not have a leak when using the vector new and delete ?