【发布时间】:2016-08-24 13:34:46
【问题描述】:
我用的是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();
它在 Debug 模式下运行良好,但在我切换到 Release 模式时会引发“访问冲突异常”。
此外,如果我尝试将“myfunc”修改为:
void Klass::myfunc() { std::cout << "foo" << std::endl; }
// ...
auto t = std::thread(&Klass::myfunc, this); // everything goes well
// ...
t.join();
它再次运行良好。
我保证 "&Klass::myfunc" 和 "this" 指针不为 NULL。调用ctor时,在几行之后有一个“join”。
我猜这可能是某种“未定义的行为”,但我不知道它到底是什么。
调用栈是这样的:
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
【问题讨论】:
-
创建线程后会发生什么?你
join了吗? -
@doctorlove 可能暗示的是,这看起来像是一个生命周期问题,其中线程比 Klass 实例寿命更长,因此有一个悬空的 this 指针。通过在正确的位置加入,您可以防止这种情况发生。但是,根据所提供的背景,我们无法确定。
-
@doctorlove stefaanv 两位您好,感谢您的回复。实际上,调试器和日志显示程序在调用 std::thread 的 ctor 后立即关闭,并且“join”在几行之后。我认为问题不在于“加入”。而且我在问题中也提到,如果我不带参数调用“myfunc”,一切都会顺利。
-
请编辑您的问题以包含minimal reproducible example
标签: c++ multithreading c++11 stdthread