【问题标题】:Why is not deleting an object that has a destructor with a side effect undefined behavior in C++11?为什么不删除具有 C++11 中具有副作用未定义行为的析构函数的对象?
【发布时间】:2012-04-15 19:49:19
【问题描述】:

This answer 引用 C++11 标准 3.8:

如果没有显式调用析构函数,或者如果没有使用删除表达式 (5.3.5) 来释放存储,则不应隐式调用析构函数,并且任何依赖于由析构函数具有未定义的行为。

没有调用析构函数的部分很清楚。现在假设跳过的析构函数有一个副作用,应该会影响程序的行为。

为什么现在程序行为未定义?为什么不跳过副作用(因为没有调用析构函数)并且程序在没有应用副作用的情况下正常运行?

【问题讨论】:

  • 有趣的问题。但是为什么有人不想在不再需要对象时调用析构函数呢?
  • 如果在这种情况下析构函数执行非平凡的任务例如:关闭资源句柄或将状态设置为有效等,那么不调用的析构函数当然会影响程序并导致未定义的行为。我不明白跳过副作用的理由。
  • @ereOn:单例已被提及为一个用例(但是,这不应该被认为是好的设计)。
  • @ereOn:std::cout(和一般登录)是您希望它们在程序运行期间一直可用的特殊情况之一。明显的潜在问题是 C++ 对全局变量的初始化和销毁​​顺序缺乏保证,不调用某些对象的析构函数是缓解 Destruction Order Fiasco 的一种方式。

标签: c++ memory-leaks c++11 destructor undefined-behavior


【解决方案1】:

重要的部分是该段的第一部分(强调我的):

程序可以通过重用对象占用的存储空间来结束任何对象的生命周期 ...

如果你只是简单地为一个析构函数没有被调用的对象重用存储,那么你会得到未定义的行为。例如,该对象可能已经启动了一个线程,或者注册了一个回调,或者外部组件可能期望该对象仍然存在的一些其他操作。

【讨论】:

  • 我不同意。完整的引号添加了或通过显式调用具有非平凡析构函数的类类型对象的析构函数。所以在这种情况下会调用析构函数。
  • 抱歉,在什么情况下?它确实说,所以我上面的引用似乎和你的一样独立。
  • 但这就是我要指出的问题。这两句话都独立存在。标准提供了一个替代方案,但选择权不是我们的。 对于具有非平凡析构函数的类类型的对象给出了在的两个分支之间进行选择的标准。因此,任何具有非平凡析构函数的对象(这是这里有趣的情况)都会在其存储被重用之前将其析构函数称为
【解决方案2】:

在这种情况下,我们确实有一个准确的答案。引入了具体的行来解决CWG 1116, "Aliasing of union members"。

【讨论】:

  • 当问题中的行已经在标准中时,似乎提出了 CWG 1116 问题。其提议的解决方案是增加一行,以“如果程序获得特定类型 A 的对象的存储...”开头。您可能是指其他问题吗?
【解决方案3】:

你的问题没有意义。

为什么不跳过副作用(因为没有调用析构函数)并且程序在没有应用副作用的情况下正常运行?

它们被跳过,因为它们会被析构函数触发并且它还没有被调用。

我的阅读:

任何依赖于析构函数产生的副作用的程序都有未定义的行为。

很简单,我是从RAII来看的。示例:

#include "Object.hpp"

struct Manager: private boost::noncopyable {
  union Raw {
    char _[sizeof(Object)];
    Object o;
  };
  static Raw raw;

  Manager() { new (raw.o) Object(); }
  ~Manager() { raw.o.~Object(); }
};

现在,如果我分配了一个 Manager,忘记销毁它,然后分配了一个新的,那么我就处于紧要关头,因为我将用第二个 Object 覆盖第一个创建的存储空间,即使它是还活着”。这是未定义的行为。

【讨论】:

    【解决方案4】:

    我相信这已被纳入标准以允许垃圾收集。并指出 C++ 的行为与其他一些语言不同,在收集时不调用析构函数。

    它明确表示可以重用存储,而无需调用该内存区域中对象的析构函数。如果程序依赖正在运行的析构函数,它将无法按预期工作。

    如果它依赖于析构函数,一切都很好。

    【讨论】:

      猜你喜欢
      • 2012-08-01
      • 2019-01-29
      • 2015-08-12
      • 2018-06-21
      • 2011-06-17
      • 2015-01-12
      • 2017-09-23
      • 2017-05-18
      • 2016-11-30
      相关资源
      最近更新 更多