【问题标题】:Exception in destructor of dynamic object动态对象的析构函数异常
【发布时间】: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


【解决方案1】:

标准说 (5.3.5p7):

如果delete-expression的操作数的值不是空指针值,delete-expression会调用一个释放函数。否则,未指定是否将调用释放函数。 [注意:无论对象的析构函数或数组的某些元素是否抛出异常,都会调用释放函数。 ——尾注]

笔记回答了你的问题。

【讨论】:

  • 确实如此!谢谢 :-) 等等,那么 GCC 中可能有错误?!
  • @Kerrek:听起来像是一场圣经危机!
猜你喜欢
  • 1970-01-01
  • 2012-12-26
  • 2023-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-21
  • 2011-07-27
  • 2019-07-30
相关资源
最近更新 更多