ama*_*ang 4 c++ visual-c++ msvc12
所以,这就是我所说的:std很复杂.
在VS2013中,这个简单的程序会导致死锁.
#include <thread>
#include <windows.h>
void foo()
{
}
void initialize()
{
std::thread t(foo);
}
BOOL APIENTRY DllMain(HMODULE, DWORD reason, LPVOID)
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
initialize();
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
Run Code Online (Sandbox Code Playgroud)
在DLLMain中创建一个线程是完全错误的?这不是真的.从Microsoft的"创建DLL的最佳实践"文档:" 如果不与其他线程同步,创建一个线程就可以工作 ".所以CreateThread工作,_beginthreadex工作,boost :: thread工作,但std :: thread不起作用.这是调用堆栈:
ntdll.dll!_NtWaitForSingleObject@12()
KernelBase.dll!_WaitForSingleObjectEx@12()
msvcr120d.dll!Concurrency::details::ExternalContextBase::Block() Line 151
msvcr120d.dll!Concurrency::Context::Block() Line 63
msvcr120d.dll!Concurrency::details::_Condition_variable::wait(Concurrency::critical_section & _Lck) Line 595
msvcp120d.dll!do_wait(_Cnd_internal_imp_t * * cond, _Mtx_internal_imp_t * * mtx, const xtime * target) Line 54
msvcp120d.dll!_Cnd_wait(_Cnd_internal_imp_t * * cond, _Mtx_internal_imp_t * * mtx) Line 81
msvcp120d.dll!std::_Cnd_waitX(_Cnd_internal_imp_t * * _Cnd, _Mtx_internal_imp_t * * _Mtx) Line 93
msvcp120d.dll!std::_Pad::_Launch(_Thrd_imp_t * _Thr) Line 73
mod.dll!std::_Launch<std::_Bind<1,void,void (__cdecl*const)(void)> >(_Thrd_imp_t * _Thr, std::_Bind<1,void,void (__cdecl*const)(void)> && _Tg) Line 206
mod.dll!std::thread::thread<void (__cdecl&)(void)>(void (void) * _Fx) Line 49
mod.dll!initialize() Line 17
mod.dll!DllMain(HINSTANCE__ * __formal, unsigned long reason, void * __formal) Line 33
Run Code Online (Sandbox Code Playgroud)
好的,std :: thread将"与其他线程同步".
但为什么 ?
我希望在VS2015中再也不会发生这种情况,我还没有测试过.
规范std::thread包含以下要求(N4527§30.3.1.2[thread.thread.constr]/6):
同步:构造函数的调用完成与调用副本的开始同步
f.
(在f新创建的线程上执行的可调用实体在哪里.)
std::thread在新线程开始执行线程过程之前,该构造函数无法返回.创建新线程时,在调用线程过程之前,将调用每个加载的DLL的入口点DLL_THREAD_ATTACH.为此,新线程必须获取加载程序锁.不幸的是,您现有的线程已经拥有加载程序锁.
因此,您死锁:现有线程无法释放加载程序锁定,直到新线程开始执行线程过程,但新线程无法执行线程过程,直到它可以获取现有线程持有的加载程序锁定.
请注意,文档明确建议不要从DLL入口点创建线程:
您永远不应该从内部执行以下任务
DllMain:[...]呼叫CreateThread.如果不与其他线程同步,则创建线程可以正常工作,但这样做有风险.
(该页面有一长串不应从DLL入口点完成的事情;这只是其中之一.)
| 归档时间: |
|
| 查看次数: |
3186 次 |
| 最近记录: |