如何在clang中处理“exit-time destructor”警告?

55

在我的C++11代码中,我遇到了以下情况的clang警告:“Declaration requires an exit-time destructor”:

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)

的内容已被翻译。
2个回答

33

全局和函数静态对象在应用程序退出时将调用它们的析构函数。这些析构函数被称为 "退出时间析构函数",它们按照被构建的相反顺序进行调用。

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

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

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


根据 someStruct 的析构函数所做的操作,我通常会谨慎防止析构函数被运行。在程序退出时,管理内存可能不再是一个问题,但其他非平凡操作仍然可能需要运行。在更复杂的情况下,很快就变得难以证明不运行析构函数没有不良影响。此外,在释放大量内存时才会注意到程序退出时的减速。 - Konrad Rudolph
1
是的,这就是为什么我说“可能”和“大多数情况”。如果您的析构函数通过某种IO与系统的其他部分交互,则需要运行这些析构函数。一个简单的例子是全局配置对象,在程序退出时将设置保存到磁盘上,并且您依赖析构函数来知道何时发生这种情况(并不是我提倡编写此类代码)。 - yiding
3
@KonradRudolph 这个结构体包含三个“const char *”。因此,我的同事正确地指出堆分配是过度的。有没有一种方法可以在不使用堆分配的情况下消除这个警告? - Lars Schneider
1
我认为它抱怨的是std::map,而不是其中的结构体。 - yiding
1
@yiding 是的。但除了我在问题中提到的堆分配 #define,还有什么我可以做的吗? - Lars Schneider
显示剩余2条评论

4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接