在示例代码中
void foo()
{
static Bar b;
...
}
Run Code Online (Sandbox Code Playgroud)
使用GCC编译是否可以保证b以线程安全的方式创建和初始化?
在gcc的手册页中,找到了-fno-threadsafe-statics命令行选项:
不要发出额外的代码来使用C++ ABI中指定的例程来进行本地静态的线程安全初始化.您可以使用此选项在不需要线程安全的代码中略微减小代码大小.
这是否意味着,默认情况下,GCC的本地静态是线程安全的?所以没有理由明确保护,例如pthread_mutex_lock/unlock?
如何编写可移植代码 - 如何检查编译器是否会添加其防护?或者关闭GCC的这个功能是否更好?
这个问题让我质疑我多年来一直遵循的做法.
对于函数本地静态const对象的线程安全初始化,我保护对象的实际构造,但不保护引用它的函数本地引用的初始化.像这样的东西:
namespace {
const some_type& create_const_thingy()
{
lock my_lock(some_mutex);
static const some_type the_const_thingy;
return the_const_thingy;
}
}
void use_const_thingy()
{
static const some_type& the_const_thingy = create_const_thingy();
// use the_const_thingy
}
Run Code Online (Sandbox Code Playgroud)
这个想法是锁定需要时间,如果引用被多个线程覆盖,那么无关紧要.
如果是的话,我会感兴趣的
我想知道这个的原因是我想知道我是否可以保留代码,或者我是否需要回去修复它.
对于探究的头脑:
我使用的许多这样的函数本地静态const对象是在首次使用时从const数组初始化并用于查找的映射.例如,我有一些XML解析器,其中标记名称字符串映射到enum值,因此我可以稍后switch覆盖标记的enum值.
由于我得到了一些关于该做什么的答案,但是没有得到我实际问题的答案(见上文1.和2.),我会对此开始赏金.还是那句话:
我不感兴趣,我能做什么,而不是,我真的想知道这个.
对于创建/使用std::threads 的类,静态局部变量是否安全?
因为当我使用这样的东西:
logger& logger::get_instance(void)
{
static logger lg;
return lg;
}
Run Code Online (Sandbox Code Playgroud)
并尝试退出(强制关闭)可执行文件,它不正确地崩溃/退出(某些事情Visual Studio 2012调试器甚至崩溃).
当我不这样做时,当我强行关闭时,程序会优雅地退出.
这是崩溃时的堆栈调用
ntdll.dll!77c10dbd() Unknown
[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll]
ntdll.dll!77b7bfdc() Unknown
kernel32.dll!75b55bab() Unknown
> msvcr110d.dll!__crtCreateThreadpoolWait(void (_TP_CALLBACK_INSTANCE *, void *, _TP_WAIT *, unsigned long) * pfnwa, void * pv, _TP_CALLBACK_ENVIRON_V1 * pcbe) Line 569 C
msvcr110d.dll!Concurrency::details::RegisterAsyncWaitAndLoadLibrary(void * waitingEvent, void (_TP_CALLBACK_INSTANCE *, void *, _TP_WAIT *, unsigned long) * callback, void * data) Line 675 C++
msvcr110d.dll!Concurrency::details::ExternalContextBase::PrepareForUse(bool explicitAttach) …Run Code Online (Sandbox Code Playgroud)