【问题标题】:How to deal with "exit-time destructor" warning in clang?如何处理clang中的“退出时间析构函数”警告?
【发布时间】:2012-12-29 10:03:47
【问题描述】:

在我的 C++11 代码中,我在以下情况下收到 clang 警告“声明需要退出时析构函数”:

static const std::map<int, const someStruct> mymap = {
    {1, {
        "A",
        "B",
        "C"
    }},
    {2, {
        "D",
        "E",
        "F"
    }}
};

据我了解,Google 需要一个“退出时析构函数”以确定性的方式销毁 main() 和静态变量,以防止由于“已发布的变量”而导致退出时崩溃。那正确吗?谁能解释的更好?

另外:我能做些什么(我不想禁用警告)?上面的代码只在一个线程的上下文中使用。

看起来这就是 Chromium 处理这些情况的方式;这也是我的情况的正确方法吗?

#define CR_DEFINE_STATIC_LOCAL(type, name, arguments) \
  static type& name = *new type arguments

(来源:https://chromium.googlesource.com/chromium/src/+/32352ad08ee673a4d43e8593ce988b224f6482d3/base/basictypes.h

【问题讨论】:

    标签: c++ c++11 warnings clang destructor


    【解决方案1】:

    全局和函数静态对象将在您的应用程序退出时调用其析构函数。这些析构函数是“退出时间析构函数”。并以与它们构建时相反的顺序被调用。

    正如您所说,如果其中一些析构函数接触到已销毁的对象,您的程序可能会崩溃。此外,在退出时运行的析构函数会使程序退出速度变慢,而且大多数情况下它们对于程序的正确性并不是必需的(因为当程序退出时,它无论如何都会释放其所有内存)。

    警告只是指出您有将在退出时运行的析构函数。

    您提出的修复将堆分配对象,这不会导致它在程序退出时自动销毁。对于您的情况,这可能已经足够了。

    【讨论】:

    • 取决于someStruct 的析构函数的作用。我通常对阻止运行析构函数持谨慎态度。在程序退出时管理内存可能不再是问题,但其他重要的操作可能仍然需要运行。在更复杂的场景中,很快就很难证明不运行析构函数没有负面影响。此外,只有在释放大部分内存时,程序退出时的减速才会明显。
    • 是的,这就是我说“可能”和“大部分时间”的原因。如果您的析构函数通过某种 IO 与系统的其余部分交互,那么您希望这些析构函数运行。一个简单的例子是一个全局配置对象,它在程序退出时将设置保存到磁盘,并且你依赖析构函数知道什么时候发生(我不提倡这样做的代码)。
    • @KonradRudolph 该结构是三个“const char *”。因此,我的同事正确地反对堆分配是矫枉过正的。有没有办法在没有堆分配的情况下使这个警告免费?
    • 我认为它抱怨的是 std::map,而不是里面的结构。
    • @yiding 真的。但是除了我的问题中的堆分配#define之外,我还能做些什么吗?
    【解决方案2】:

    查看属性 no_destroy/always_destroy https://clang.llvm.org/docs/AttributeReference.html

    【讨论】:

      猜你喜欢
      • 2013-03-20
      • 1970-01-01
      • 1970-01-01
      • 2015-01-07
      • 2023-03-18
      • 2017-05-01
      • 1970-01-01
      相关资源
      最近更新 更多