【发布时间】:2012-11-27 09:30:11
【问题描述】:
我遇到了这个我通常会用“don't do that”驳回的边缘问题,但我在标准中找不到令人满意的答案,如果有人能指出原因,我将不胜感激:
假设我有一个在析构函数中抛出异常的类:
struct Foo { ~Foo() { throw std::runtime_error("Catch this!"); } };
如果我删除该类的动态分配实例,动态分配的内存会发生什么情况?
auto p = new Foo;
try { delete p; }
catch (std::exception const &) { }
释放函数是否被调用?为什么?我可以通过将operator delete(p); 添加到catch 块中来使此代码正确吗?
我用 GCC 进行了一个小测试,它似乎不会自动释放内存。 (将此与 构造函数 中的异常进行对比,在这种情况下,保证会调用释放函数(如果存在)。
【问题讨论】:
-
不,您不能通过添加
operator delete(p)来使其正确,除非您使用operator new()和placement new 来构造对象,然后您还需要显式调用析构函数。通常,您需要将指向原始分配缓冲区的指针和指向对象的指针分开。 (对于数组,它们甚至可能没有相同的地址。) -
@BenVoigt:你能以某种方式备份它吗?我刚刚注意到添加
operator delete(p)似乎确实使我的程序 valgrind-clean,但这实际上是 UB 吗?new表达式不是保证调用operator new吗? -
标准规定“如果对象是数组,则创建的对象的地址不一定与块的地址相同。”此外,调用释放函数的规则要求您从匹配的分配函数中获取指针。
-
@ChrisW:问题已经说过了。当你违背所有理智的建议时,找出规则是什么仍然很有趣。
标签: c++ exception destructor language-lawyer dynamic-allocation