I am not absolutely sure what is happening in the code below:
#include <iostream>
struct Foo
{
double dummy{42};
static void* operator new(std::size_t size, void* p)
{
std::cout << R"(Calling placement "operator new" for size )"
<< size << '\n';
return ::operator new(size, p);
}
Foo()
{
std::cout << "Foo::Foo()" << std::endl;
}
~Foo()
{
std::cout << "~Foo::Foo()" << std::endl;
}
};
int main()
{
void* buf_heap = new char[128] {};
Foo* pFoo_heap = new(buf_heap) Foo; // placement allocation
// why does this line call the correct operator delete?
delete pFoo_heap;
// the line above seems to be equivalent to:
// pFoo_heap->~Foo();
// ::operator delete(buf_heap);
}
I know that whenever one uses placement new
when constructing an object, the destructor should be manually called, followed by a call to release the memory (usually via ::operator delete
or ::operator delete[]
, or free
, depending on how placement new
is implemented), see e.g. How to delete object constructed via placement new operator?
However, in my code above, I created a Foo
object which I placed in heap-allocated memory. Then, when I call delete pFoo_heap
, the destructor is automatically invoked (this I understand), however it seems also that the memory is also released (buf_heap
in this case). That is, if I try after to do ::operator delete[](buf_heap);
I'm getting a segfault.
So basically the line
delete pFoo_heap;
seems to be equivalent to
pFoo_heap->~Foo();
::operator delete[](buf_heap);
Is this indeed the case (or it is just UB)? Why is the memory allocated in buf_heap
de-allocated? Or, in other words, does delete pFoo_heap;
know where the memory came from, even if allocated via a placement new
?