前言
c++11 担保了 static 变量的初始化线程安全。但是老的c++标准并没有担保,所以说老版本的编译器可能static 变量初始化在多线程的条件下会造成问题
c++ 98/03 关于静态初始化标准
下面是老版本标准对这个问题的描述,简言而之它只是担保了local static 变量的初始化发生于当该表达式第一次执行时。
Here’s an excerpt from section 6.7 of a working draft (N1095) of the current C++ standard (C++98)
The zero-initialization (8.5) of all local objects with static storage duration (3.7.1) is performed before any other initialization takes place. A local object of POD type (3.9) with static storage duration initialized with constant-expressions is initialized before its block is first entered. An implementation is permitted to perform early initialization of other local objects with static storage duration under the same conditions that an implementation is permitted to statically initialize an object with static storage duration in namespace scope (3.6.2). Otherwise such an object is initialized the first time control passes through its declaration; such an object is considered initialized upon the completion of its initialization.
大多数编译器选择 在 全局作用域内的static 变量会在进入main函数前初始化,而 func内的local static 变量只会在该函数第一次被调用的时候初始化。这就造成了一个问题,可能函数内部的static local 变量的初始化不是线程安全的,所以我们不能假设 static local 变量的初始化就是线程安全的。
编译器的实现
demo
#include <iostream>
using namespace std;
class Foo {
public:
Foo(const char* s = "") {
cerr << "Constructing Foo with " << s << endl;
}
};
void somefunc()
{
static Foo funcstatic("funcstatic");
Foo funcauto("funcauto");
}
static Foo glob("global");
int main()
{
cerr << "Entering main\n";
somefunc();
somefunc();
somefunc();
return 0;
}
vs2008 实现
现在看看somefunc 这个 local static 变量初始化函数的实现。
static Foo funcstatic("funcstatic");
00E314FD mov eax,dword ptr [$S1 (0E3A148h)]
00E31502 and eax,1
00E31505 jne somefunc+71h (0E31531h)
00E31507 mov eax,dword ptr [$S1 (0E3A148h)]
00E3150C or eax,1
00E3150F mov dword ptr [$S1 (0E3A148h)],eax
00E31514 mov dword ptr [ebp-4],0
00E3151B push offset string "funcstatic" (0E3890Ch)
00E31520 mov ecx,