我在我正在处理的一些代码中遇到了一个线程问题。 MyStruct在多个线程上构造,导致程序有时在staticFunc中崩溃。代码正在访问不安全的变量值(MSVC 2012编译器),这是一个惊喜。
struct MyStruct : baseClass
{
MyStruct() : baseClass(myFunc())
{
}
static int* myFunc()
{
static int value[const_size] = get_array();
// Do some complex stuff to value.
return &value[0];
}
};
我的问题是,解决这个问题的最佳方法是什么? 我的第一个想法是一起删除静态声明。 这实际上允许我写的单元测试通过。
struct MyStruct : baseClass
{
MyStruct() : baseClass(myFunc())
{
}
int* myFunc()
{
this->value = get_array();
// Do some complex stuff to value.
return &this->value[0];
}
int value[const_size];
};
但是我担心,如果在构造/初始化之前使用了值,那么它是不是未定义的行为?
施工顺序:
这是发生了什么,或者我错过了什么,如果是这样,解决这个问题的正确方法是什么?静态互斥?
编辑:我正在使用MSVC 2012(静态不是线程安全的)并且移动到不同的编译器不是一个选项。
答案 0 :(得分:0)
第一个问题是你是想在不同线程之间共享值,还是每个线程都可以存储自己的值。
如果要跨线程共享值,则需要使用Critical Section保护所有访问。
如果您对使用不同值的不同线程没问题,则需要查看线程本地存储。 c ++ 11为此提供了thread_local,但我不确定MSVC是否支持此功能。否则你可以使用TlsAlloc,TlsGetValue,TlsSetValue和TlsFree。
答案 1 :(得分:0)
使用std::call_once
,它实际上是为解决这个问题而发明的。从内存开始,您不需要针对文件范围静态的线程安全静态,因为它们必须在输入main
之前进行初始化,因此任何人都不可能在您的代码中有任何线程它被初始化了。
// Place the func_flag at file scope.
static std::once_flag my_func_flag;
class blah {
static const int* myFunc()
{
static int value[const_size];
std::call_once(my_func_flag, [] {
// perform ALL mutations of value in here.
value = get_array();
});
// Read-only from here on.
return &value[0];
}
};