【发布时间】:2015-06-24 21:53:32
【问题描述】:
我不确定以下代码中发生了什么:
#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);
}
我知道每当在构造对象时使用放置new 时,都应手动调用析构函数,然后调用释放内存(通常通过::operator delete 或::operator delete[] 或free,具体取决于关于放置new 是如何实现的),参见例如How to delete object constructed via placement new operator?
但是,在我上面的代码中,我创建了一个 Foo 对象,我将它放在堆分配的内存中。然后,当我调用delete pFoo_heap 时,会自动调用析构函数(我理解),但是似乎内存也被释放了(在这种情况下为buf_heap)。也就是说,如果我尝试执行::operator delete[](buf_heap);,我会遇到段错误。
所以基本上是一行
delete pFoo_heap;
似乎等价于
pFoo_heap->~Foo();
::operator delete[](buf_heap);
确实是这样(或者只是UB)?为什么buf_heap中分配的内存被取消分配了?或者,换句话说,delete pFoo_heap; 是否知道内存来自哪里,即使是通过放置new 分配的?
【问题讨论】:
-
猜猜:你很幸运,因为你放置的对象和堆块从同一个地址开始。尝试在
buf_heap中间分配pFoo_heap看看会发生什么。 -
@RichardCritten 很棒的评论,我没想到这一点。所以这是UB的一个很好的例子......
标签: c++ memory-management placement-new