静态顺序初始化失败,iostream 和 C++11

Static order initialization fiasco, iostream and C++11

根据 C++11 规范:

The results of including <iostream> in a translation unit shall be as if <iostream> defined an instance of ios_base::Init with static storage duration. Similarly, the entire program shall behave as if there were at least one instance of ios_base::Init with static storage duration

这意味着如果我的代码看起来像这样:

// A.cpp
#include <iostream>
using namespace std;
unsigned long foo() {
    cerr << "bar"; 
    return 42;
}

// B.cpp

using namespace std;
extern unsigned long foo();

namespace {
unsigned long test() {
    int id = foo();
    return id;
}

unsigned long id = test();
}


int main() {
     return 0;
}

那么我应该可以安全地调用 cerr,而不会有静态初始化失败的风险。

不幸的是,该代码出现段错误...为什么?我不认为 gcc 6.2.1 决定忽略 C++11 规范,我在 A.cpp 中包含了 <iostream>。根据规范应该足够了。

该段的完整引用包括:

The objects are constructed and the associations are established at some time prior to or during the first time an object of class ios_base::Init is constructed, and in any case before the body of main begins execution. 293)

还有脚注

293) If it is possible for them to do so, implementations are encouraged to initialize the objects earlier than required.

因此,保证 iostream 在进入 main 时最迟 工作。没有严格要求他们应该早点工作,除非翻译单元包括 <iostream>.

你找到了绕过这个的方法!

从 B.cpp 调用 foo() 时,A.cpp 中包含的 ios_base::Init 实例可能已初始化,也可能未初始化。