问题
I've encounter a bug in Visual Studio 11 Developer Preview, at least I think it is a bug and reported it, but I'm interested whether someone know a workaround.
When I use std::thread
class to create more then one thread it causes application to crash. Sometimes it throws exception, sometimes it causes access violation and sometimes it works. Code that reproduces the bug looks like this:
#include <iostream>
#include <thread>
#include <vector>
#include <Windows.h>
int _tmain(int argc, _TCHAR* argv[])
{
std::vector<std::thread*> threads;
for(int i = 0; i < 10; i++)
{
threads.push_back(new std::thread([i]
{
/*std::cout << "thread " << i << std::endl;*/
/* whatever else that is thread safe, or even an empty lambda */
}));
}
for(int i = 0; i < 10; i++)
{
threads[i]->join();
delete threads[i];
}
return 0;
}
It doesn't matter whether the static or dynamic CRT libraries are used (all of them are multi-threaded)..
bug report
Stacktrace (thrown exception, unlocking unowned mutex):
test.exe!_NMSG_WRITE(int rterrnum) Line 217 C
test.exe!abort() Line 62 C
test.exe!_Thrd_abort(const char * msg) Line 111 C
test.exe!_Mtx_unlock(_Mtx_internal_imp_t * * mtx) Line 206 C++
test.exe!_Save_state(_Mtx_internal_imp_t * * mtx, _Mtx_state * state) Line 266 C++
test.exe!do_wait(_Cnd_internal_imp_t * * cond, _Mtx_internal_imp_t * * mtx, const xtime * target) Line 103 C
test.exe!_Cnd_wait(_Cnd_internal_imp_t * * cond, _Mtx_internal_imp_t * * mtx) Line 198 C
test.exe!std::_Cnd_waitX(_Cnd_internal_imp_t * * _Cnd, _Mtx_internal_imp_t * * _Mtx) Line 94 C++
test.exe!std::_Pad::_Launch(_Thrd_imp_t * _Thr) Line 97 C++
test.exe!??$_Launch@V?$_Bind@$0A@XV<lambda_1B7F0477D0C0EDFD>@?4?wmain@U_Nil@std@@U23@U23@U23@U23@U23@U23@@std@@@std@@YAXPAU_Thrd_imp_t@@ABV?$_Bind@$0A@XV<lambda_1B7F0477D0C0EDFD>@?4?wmain@U_Nil@std@@U23@U23@U23@U23@U23@U23@@0@@Z(_Thrd_imp_t * _Thr, const std::?$_Bind@$0A@XV<lambda_1B7F0477D0C0EDFD>@?4?wmain@U_Nil@std@@U23@U23@U23@U23@U23@U23@ & _Tg) Line 207 C++
test.exe!main::main(wmain::__l5::<lambda_1B7F0477D0C0EDFD> _Fx) Line 47 C++
test.exe!wmain(int argc, wchar_t * * argv) Line 17 C++
test.exe!__tmainCRTStartup() Line 238 C
test.exe!wmainCRTStartup() Line 168 C
kernel32.dll!76d7339a() Unknown
[Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll]
ntdll.dll!77cc9ef2() Unknown
ntdll.dll!77cc9ec5() Unknown
Stacktrace (access violation):
test.exe!_Mtx_unlock(_Mtx_internal_imp_t * * mtx) Line 218 C++
test.exe!std::_Mtx_unlockX(_Mtx_internal_imp_t * * _Mtx) Line 84 C++
test.exe!std::_Pad::_Release() Line 105 C++
test.exe!?_Run@?$_LaunchPad@V?$_Bind@$0A@XV<lambda_1B7F0477D0C0EDFD>@?4?wmain@U_Nil@std@@U23@U23@U23@U23@U23@U23@@std@@@std@@CAIPAV12@@Z(std::?$_LaunchPad@V?$_Bind@$0A@XV<lambda_1B7F0477D0C0EDFD>@?4?wmain@U_Nil@std@@U23@U23@U23@U23@U23@U23@@std@@ * _Ln) Line 195 C++
test.exe!?_Go@?$_LaunchPad@V?$_Bind@$0A@XV<lambda_1B7F0477D0C0EDFD>@?4?wmain@U_Nil@std@@U23@U23@U23@U23@U23@U23@@std@@@std@@UAEIXZ() Line 187 C++
test.exe!_Call_func(void * _Data) Line 52 C++
test.exe!_callthreadstartex() Line 308 C
test.exe!_threadstartex(void * ptd) Line 291 C
kernel32.dll!76d7339a() Unknown
[Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll]
ntdll.dll!77cc9ef2() Unknown
ntdll.dll!77cc9ec5() Unknown
Thanks!
回答1:
This is a known issue. See the following Connect bug:
std::thread crashes with error "f:\dd\vctools\crt_bld\self_x86\crt\src\thr\mutex.cpp(206): unlock of unowned mutex"
In the comments of that bug report, Stephan says, "We've fixed it, and the fix will be available in VC11." (Whether the fix will be present in the VC11 Beta, I do not know. We'll find out next week.)
回答2:
I haven't had any problems with threads in the VS11 dev preview. The following works for me. I must be using slightly different build settings because I had to remove the references to _TCHAR
. If it's not a new bug since the dev preview then maybe messing around with the build settings will help. The scratch project I'm using should mostly be the default. The only thing I remember change was manually disabling and deleting the precompiled header stuff, because unchecking that check box in the project creation wizard never does anything.
#include <iostream>
#include <thread>
#include <vector>
#include <Windows.h>
int main(int argc, char* argv[])
{
std::vector<std::thread*> threads;
for(int i = 0; i < 10; i++)
{
threads.push_back(new std::thread([i]
{
std::cout << "thread " << i << std::endl;
/* whatever else that is thread safe, or even an empty lambda */
}));
}
for(int i = 0; i < 10; i++)
{
threads[i]->join();
delete threads[i];
}
return 0;
}
Also you don't need pointers. You can use std::vector<std::thread>
(or std::array
) because std::thread
is movable.
std::array<std::thread,10> threads;
for(int i = 0; i < threads.size(); i++)
threads[i] = std::thread([i] { std::cout << "thread " << i << std::endl; });
for(int i = 0; i < 10; i++)
threads[i].join();
来源:https://stackoverflow.com/questions/9421235/stdthread-class-in-vc-11-causes-random-crashes-any-workarounds