5

Can we call delete on the pointer which is allocated with the placement new? If no then why? Please explain in details.

I know that there is no placement delete. But I wonder why just delete opetator can not delete the memory without caring how that memory on which the pointer points is allocated?

delete is doing two things:

  1. Calls destrucor
  2. Frees memory

And I see no reaason for delete not to be able to call either of these two operations on the object which was created by placement new. Any idea about reasons?

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
Narek
  • 38,779
  • 79
  • 233
  • 389

5 Answers5

8

You must only call delete on pointers that were created with operator new. If you use placement new with a memory location that was allocated by the normal operator new then you may safely use delete on it (provided you get the types and pointers right). However, you can use placement new on any memory, so you usually will manage that memory some other way and call the object's destructor manually.

For instance, in this convoluted and usually unnecessary scenario, it is safe to delete the memory you used placement new on, but only because you allocated it with new before:

char* mem = new char[sizeof(MyObject)];
MyObject* o = new (mem) MyObject;

// use o

o->~MyObject(); // with placement new you have to call the destructor by yourself

delete[] mem;

However, this is illegal:

char mem[16]; // create a buffer on the stack, assume sizeof(MyObject) == 16

MyObject* o = new (mem) MyObject; // use stack memory to hold a MyObject
                                  // note that after placement new is done, o == mem
                                  // pretend for this example that the point brought up by Martin in the comments didn't matter

delete o; // you just deleted memory in the stack! This is very bad

Another way to think of it is that delete only deallocates memory allocated previously by the normal new. With placement new, you do not have to use memory that was allocated by the normal new, so with the possibility of not having been allocated by normal new, delete cannot deal with it.

Seth Carnegie
  • 73,875
  • 22
  • 181
  • 249
  • Also note that `char mem[16]` is not guaranteed to be aligned correctly for anything but char. When using placement new you should always do it it on dynamically allocated memory. – Martin York Aug 14 '11 at 18:00
  • @Martin if you use an array of `char` that was dynamically allocated, is it guaranteed to be aligned correctly for everything? – Seth Carnegie Aug 14 '11 at 18:02
  • Yes. With the one caveat is the space you allocate must be at least as large as the object you want to align for. Which usually is not a problem as otherwise you could not use it for placement new anyway. – Martin York Aug 14 '11 at 21:23
5

No, since delete not only calls the destructor but also frees the memory, but if you used placement new you must have allocated the memory yourself using malloc() or stack. You do, however, have to call the destructor yourself. Also see the C++ FAQ.

Antti
  • 11,944
  • 2
  • 24
  • 29
  • Actually I came from this FAQ :). There is written that you should call destructor explicitly, and I could understand why just delete operator does not call ther destructor and free the memeory if the memery was allocated by placement new. – Narek Aug 14 '11 at 17:38
  • To be precise, placement new doesn't allocate memory, it only places the new object to the memory that was already allocated. As delete can't say who allocated the memory and how, it can't free it. – Antti Aug 14 '11 at 19:33
  • But why detelte should know "who allocated the memory and how". His job is to call a dtor and free the memory, that's it! Why delete needs "historical details"? – Narek Aug 15 '11 at 07:37
  • new and delete are the interface of the memory allocator. Behind the scenes, they hold a linked list of memory chunks which are retrieved from the OS and passed to the user with new, and delete can only free memory that was allocated with new. It can't free memory that was allocated on stack, for example, because it is not its job and has no knowledge of it. – Antti Aug 15 '11 at 15:52
5

EDIT1: I know that there is no placement delete. But I wonder why just delete opetator can not delete the memory without caring how that memory on which the pointer points is allocated?

Because each flavour of memory allocation uses some implementation specific tracking of the memory (usually a header block that precedes the user address) and this make the allocation/deallocation to work only when paired up correctly:

  • new must pair with delete
  • new[] must pair with delete[] (most implementations though forgive mixing the newand new[])
  • malloc and frieds must pair with free
  • CoTaskMemAlloc pairs with CoTaskMemFree
  • alloca pairs with nothing (stack unwinding takes care of it)
  • MyCustomAllocator pairs with MyCustomFree

Attempting to call the wrong deallocator will result in unpredictable behavior( most likely seg fault now or later). Therefore calling delete on memory allocated by anything else other than new will result in bad things.

Furthermore the placement new may be called on any address, may not even be an allocated address. It can be called on an address located in the middle of some larger object, it may be called on a memory mapped region, it may be called on a raw virtual committed region, anything goes. delete woul attempt, in all these cases, to do what its implementation tell him to do: subtract the header size, interpret it as a new header, link it back into the heap. Kaboom.

The one that know how to release the memory of a placement new address is you, since you know exactly how was that memory allocated. delete will only do what it knows, and it may not be the right thing.

Remus Rusanu
  • 288,378
  • 40
  • 442
  • 569
  • Thanks, seems some understud my question!!! +1 though I would like to know more details about "some implementation specific tracking of the memory". could you please suggest a link? – Narek Aug 15 '11 at 07:42
  • Here is a discussion of `malloc` works on Mac: http://cocoawithlove.com/2010/05/look-at-how-malloc-works-on-mac.html, with links to source. – Remus Rusanu Aug 15 '11 at 15:10
0

No. There is no placement-delete expression.

Typical scenario:

void * const addr = ::operator new(sizeof(T));  // get some memory

try {
  T * const pT = new (addr) T(args...);    // construct
  /* ... */
  p->~T();                                      // nap time
}
catch (...) {
}
::operator delete(addr);  // deallocate
                          // this is _operator_-delete, not a delete _expression_

Note that the placement-new operator does have a corresponding delete operator which is mandated to be precisely void ::operator delete(void* [, size_t]) { }, a no-op; this is what gets called if the constructor of T throws an exception.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • I know that there is no placement delete, but why just delete opetator can not delete the memory without caring how that memory on which the pointer points is allocated? – Narek Aug 14 '11 at 17:33
  • @Narek because `delete` _only_ deallocates memory that was allocated by `new`, but with `placement new`, you can use memory that was _not_ allocated by normal `new`, so normal `delete` cannot take care of that. – Seth Carnegie Aug 14 '11 at 17:35
  • The ordinary delete operator can only delete memory that has been obtained by the ordinary new operator. As you can see, that's exactly how I am using it in the example. The memory that you pass to the placement-new expression, and consequently to the placement-new operator, comes from elsewhere and is none of the placement-delete's business. If you think about it, the placement-delete *operator* does in fact "free" the memory obtained from the placement-new operator, namely by doing nothing, which is exactly what the placement-new operator did to *obtain* the memory. – Kerrek SB Aug 14 '11 at 17:36
  • Also, please be sure not to conflate allocation/deallocation with construction/destruction. The former is the *operator*'s job, the latter is the job of the *expression*. Since there is no placement-delete *expression*, you have to call the destructor manually. – Kerrek SB Aug 14 '11 at 17:37
0

No, because a placement new doesn't allocate any memory. You use placement new on previously allocated raw memory. The only thing it does is call the constructor of the object.

Christian Rau
  • 45,360
  • 10
  • 108
  • 185