我使用VS2015并在使用std :: thread时遇到一个非常奇怪的问题。
void Klass::myfunc(int a, int b) { std::cout << a << ' ' << b << std::endl; }
// ...
auto t = std::thread(&Klass::myfunc, this, 100, 200); <- runtime error after called
// ...
t.join();
它在调试模式下运行良好,但会引发&#34;访问冲突异常&#34;当我转向发布模式时。
还有什么,如果我尝试修改&#34; myfunc&#34;对此:
void Klass::myfunc() { std::cout << "foo" << std::endl; }
// ...
auto t = std::thread(&Klass::myfunc, this); // everything goes well
// ...
t.join();
再次运作良好。
我保证&#34;&amp; Klass :: myfunc&#34;和&#34;这个&#34;指针不是NULL。还有一个&#34;加入&#34;在调用ctor之后的几行之后。
我想这可能是某种&#34;未定义的行为&#34;但我不知道究竟是什么。
调用堆栈是这样的:
000000c83a4ffd40() Unknown
> distributed_word_embedding.exe!std::_LaunchPad<std::unique_ptr<std::tuple<void (__cdecl multiverso::Communicator::*)(void) __ptr64,multiverso::Communicator * __ptr64>,std::default_delete<std::tuple<void (__cdecl multiverso::Communicator::*)(void) __ptr64,multiverso::Communicator * __ptr64> > > >::_Run(std::_LaunchPad<std::unique_ptr<std::tuple<void (__cdecl multiverso::Communicator::*)(void),multiverso::Communicator *>,std::default_delete<std::tuple<void (__cdecl multiverso::Communicator::*)(void),multiverso::Communicator *> > > > * _Ln) Line 247 C++
distributed_word_embedding.exe!std::_Pad::_Call_func(void * _Data) Line 210 C++
ucrtbase.dll!00007ffabdc7be1d() Unknown
kernel32.dll!00007ffabfae8102() Unknown
ntdll.dll!00007ffac26bc5b4() Unknown
答案 0 :(得分:0)
您应该始终确保加入(或可能分离)thread
,否则main
尤其是使用对象的线程(在这种情况下为this
)将会(有时)导致问题。
//... details omitted...
int main()
{
auto t = std::thread(&Klass::myfunc, this);
t.join(); //<----- NOTE THIS
}
Anthony William的线程blog详细介绍了这一点。举个例子与你的第二个非常相似:
void my_thread_func()
{
std::cout<<"hello"<<std::endl;
}
int main()
{
std::thread t(my_thread_func);
}
他说
然后,他介绍了如上所述使用如果您编译并运行这个小应用程序,会发生什么?可以 打印你好我们想要的?嗯,实际上没有任何说服力。它 可能会或不会。我多次运行这个简单的应用程序 在我的机器上,输出不可靠:有时输出 “你好”,带换行符;有时它输出“你好”没有 换行,有时它没有输出任何东西。那是怎么回事? 当然这样一个简单的应用程序应该可预测吗?
join
的想法,然后说,
问题是我们不是在等待我们的线程完成。当。。。的时候 执行到达main()结束程序终止, 无论其他线程在做什么。