gpt4 book ai didi

c++ - 带有静态变量的静态方法的重入

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:27:52 25 4
gpt4 key购买 nike

最近我的公司开始了从 Visual Studio 2010 升级到 Visual Studio 2015 的过程。我们目前遇到的问题显然源于编译器行为的变化。我们可以构建并运行我们的解决方案,但它似乎死锁了(它似乎只是闲置:CPU 使用率几乎为 0)。

通过调试器,我们发现了一个问题,即单例对象在初始化期间依赖于自身。这是一个极其精简的版本:

#include <iostream>
using namespace std;

struct Singleton
{
Singleton( int n )
{
cout << "Singleton( " << n << " )" << endl;
cout << Singleton::Instance().mN << endl;
mN = n;
}

static Singleton& Instance()
{
static Singleton instance( 5 );
return instance;
}

int mN;
};

int main() {
cout << Singleton::Instance().mN << endl;
return 0;
}

当然,在我们的代码中还有很多其他事情在发生,但这段代码表现出与我们在主项目中看到的相同的行为。在 VS2010 中,这会“正常”构建、运行和终止。在 VS2015 中它死锁了。

我还在 ideone.com 上用各种版本的 C++ 尝试过这个,所有这些都重现了死锁行为。这对我来说是行不通的(也不应该行得通),因为对象不应该依赖于自身。

我更好奇的是,为什么这个在 VS2010 中“有效”?标准对静态变量初始化有什么看法?这只是 VS2010(可能更早)的编译器错误吗?

最佳答案

标准说:

If control enters the declaration concurrently while the [block-scope variable with static or thread storage duration] is being initialized, the concurrent execution shall wait for completion of the initialization. If control re-enters the declaration recursively while the variable is being initialized, the behavior is undefined.

([stmt.dcl]/4)

C++11 的变化是局部静态变量的初始化需要线程安全。标准不允许在初始化期间再次通过声明的递归,并且导致的 UB 在您的情况下表现为死锁——这是完全有道理的,因为第二次通过声明是永远等待第一个完成。

现在,这在 C++03 中也是未定义的行为,但在 C++03 实现中,初始化不需要线程安全,所以可能发生的情况是:在第一次通过声明,设置标志,然后调用构造函数;第二遍看到标志,假设变量已经初始化,然后返回对它的引用。然后初始化完成。

显然,您应该重写代码以避免这种递归初始化。

关于c++ - 带有静态变量的静态方法的重入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33114896/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com