静态对象和全局对象的销毁顺序是啥?

Posted

技术标签:

【中文标题】静态对象和全局对象的销毁顺序是啥?【英文标题】:What is the order of destruction for static objects and global objects?静态对象和全局对象的销毁顺序是什么? 【发布时间】:2021-10-26 06:58:45 【问题描述】:

如果在一个程序中我创建了一个 meyer 单例和一个在其构造函数和析构函数中都使用这个 meyer 单例的对象,那么只要使用 meyer 单例的对象在单例本身之前被销毁(就像它是在函数范围内)。

现在,如果我将同一个对象设为全局对象,我会看到 seg 错误。原因是单例在全局对象之前被销毁。

这是编译器定义的行为还是标准定义的行为?我们有什么办法可以修改这种行为?

任何指针将不胜感激。

【问题讨论】:

initialization 和destruction 的顺序是部分定义的。最重要的部分是translation units之间的顺序没有定义。 销毁顺序与构造完全相反(按完成顺序),但翻译单元之间的构造顺序未指定。 Meyer 的单例应该可以防止这个问题,所以听起来你的单例实现至少有一个问题。请发帖minimal reproducible example。 见Static Initialization Order Fiasco(也适用于销毁)。 【参考方案1】:

静态对象和全局对象的销毁顺序是什么?

具有静态存储持续时间的对象的销毁顺序与它们的初始化顺序相反。

这是编译器定义的行为还是标准定义的行为?

破坏的逆序是标准的。

非本地静态对象的初始化顺序与单个翻译单元内的声明顺序相同。未指定跨翻译单元的顺序。本地静态对象在执行第一次通过它们的声明时被初始化。

我们有什么办法可以修改这种行为吗?

您可以通过重新排序声明来影响翻译单元中非本地静态对象的初始化顺序。您可以通过提前或稍后调用该函数来影响本地静态对象的初始化顺序。改变初始化的顺序会间接影响破坏的顺序。

您不能影响翻译单元之间具有静态存储持续时间的非本地对象的初始化顺序,并且您不能依赖该顺序。

【讨论】:

您写道“非本地静态对象的初始化顺序与单个翻译单元内的声明顺序相同。翻译单元之间的顺序未指定。”我的问题是上面引用的语句中的“您是在谈论静态初始化还是动态初始化”?你也可以找到源代码。你的说法是否等同于说“不同翻译单元中静态变量的初始化是不确定的”。这适用于动态初始化。 @AanchalSharma 我说的是动态初始化阶段。据我所知,静态初始化阶段(静态对象)的顺序是无关紧要的,因为它不能有相互依赖关系。 @AanchalSharma 源是 C++ 标准。请参阅 [basic.start.dynamic]、[basic.start.term]、[stmt.dcl] 部分。 @AanchalSharma Is your statement equivalent to saying "Initialization of static variables in different translation units is indeterminately sequenced." 是的。这将是一种在技术上更准确的说法。

以上是关于静态对象和全局对象的销毁顺序是啥?的主要内容,如果未能解决你的问题,请参考以下文章

C++ 并发销毁

C++11是不是指定了静态/全局变量的构造顺序?

java中静态成员变量、实例变量、局部变量何时创建、何时销毁?

Java静态方法,静态变量,初始化顺序

Effective Java阅读笔记——创建和销毁对象

为啥 Python 在对象之前销毁类变量?