内置对象/库的静态初始化顺序失败
Static initialization order fiasco for built-in objects/libraries
如果我有一些变量是静态初始化的(在main
开始之前),我可以自由使用这些构造函数中的任何内置内容吗,比如<iostream>
或<vector>
?
发生"静态初始化顺序惨败"是因为未定义静态变量(在不同的转换单元之间)的初始化顺序。
那么,如果像这样良性的东西呢
std::cout << "Hello" << std::endl;
碰巧依赖于<iostream>
中的某个静态变量提前初始化?(我并不是说它有,但假设它有。)什么意思是说内置库中的这些静态变量在我自己的静态变量之前初始化?比如说"Person.cpp"
之类的。
编辑:std::cout是否保证初始化?被建议作为这个问题的重复。然而,我认为我的问题范围稍宽,因为它询问任何标准内置库,而不仅仅是<iostream>
。
C++
标准在main开始之前或main完成之后没有对程序的行为做出强有力的声明。
根据经验,我发现了许多问题,C++运行时破坏了一些对象(例如,用于管理std::mutex的资源),这在破坏复杂类型时造成了死锁。
我建议静态的采用以下模式
C++按照执行顺序在函数中创建声明为静态的对象。这留下了一个模式,它将确保对象在需要时存在。
AnObject * AnObject::getInstance() {
static AnObject a;
return &a;
}
应执行此操作以获取全局,并将在调用getInstance()
时发生。
C++11以后
该代码保证是线程安全的,如果多个执行线程到达getInstance
,则只有一个线程将构造对象,其余线程将等待。
C++11之前
创建此模式将用线程安全问题替换定义不清的顺序。
幸运的是,可以在main中创建一个criticalsection/mmutex primary,它可以进行仲裁。
在某些操作系统(例如InitializeCriticalSection和Windows)中,这些锁可以在main之前安全地创建为静态变量。
AnObject * AnObject::getInstance() {
EnterCriticalSection( &aObjectcrit );
static AnObject a;
LeaveCriticalSection( &aObjectcrit );
return &a;
}
假设您已经在中或调用此函数之前初始化了Objectcrit。
这种模式的结果是洋葱结构的一种形式,其中对象按需要的顺序被需要,当程序退出时,它们按创建时的相反顺序被销毁。
您混淆了对象(std::cout
)和类型(std::vector
)。前者包含在关联问题中,后者是一种类型。静态初始化适用于对象,但不适用于类型。
- lambda 作为接受其他参数的参数的初始化顺序
- 大括号或等于初始值设定项初始化顺序
- C++ 模板中的静态常量初始化顺序
- 视觉C++:在 DLL 加载期间,全局变量初始化顺序是否具有确定性?
- 销毁 pthread 互斥体和 C++ 中的取消初始化顺序
- 线程局部变量的初始化顺序
- 类静态变量初始化顺序
- 具有静态存储持续时间的常量初始化变量的初始化顺序
- 解析 CRTP 初始化顺序
- 内联初始化的静态 const 类成员的初始化顺序保证
- 使用constexpr的全局初始化顺序
- 初始化与类类型相同的静态成员(静态初始化顺序问题)
- 为什么结构属性声明和初始化顺序的行为是这样的?
- 影响初始化顺序(以C++为单位)
- MSVC 2017 在单个翻译单元中违反静态初始化顺序
- C++11 成员类初始化顺序
- 同一函数中的静态函数变量初始化顺序
- 静态内联成员初始化顺序
- C++静态初始化顺序:添加到映射中
- 静态成员的静态阵列:初始化顺序惨败的可能性