静态变量初始化与线程安全

本文探讨了C++98/03标准下静态变量初始化可能存在的线程安全问题,以及不同编译器如VS2008和GCC的实现差异。C++11开始保证了静态变量初始化的线程安全,但在旧版本中,局部静态变量的初始化可能在多线程环境下不安全。文章提供了示例和汇编代码来说明这一点,并建议程序员遵循标准,避免做出不必要的假设。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

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,
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值