基类构造函数启动纯虚派生线程后阻塞执行的未定义行为问题
实验性C++代码的崩溃问题分析
注意:这仅为实验性代码,绝不应在实际开发中编写。
示例代码
class Base { protected: std::thread m_thread; std::mutex m_mutex; std::condition_variable m_condv; virtual void DerivedThread() = 0; public: Base() { m_thread = std::thread(&Base::DerivedThread, this); std::unique_lock<std::mutex> lck(m_mutex); m_condv.wait(lck); } }; class Derived : Base { protected: void DerivedThread() override { m_condv.notify_one(); } public: Derived() : Base() {} ~Derived() { m_thread.join(); } }; int main() { Derived foo; return 0; }
代码逻辑说明
基类Base的构造函数会启动一个线程执行纯虚方法DerivedThread,随后阻塞执行并等待该线程发送的条件变量信号。
崩溃现象
上述代码在MSVC x86_64调试模式(编译选项/std:c++20 /Od)下会在type_traits库中崩溃,调试栈追踪信息如下:
ucrtbased.dll() Unknown ucrtbased.dll() Unknown ucrtbased.dll() Unknown vcruntime140d.dll() Unknown > TestMain.exe!std::invoke<void (__cdecl Base::*)(void),Base *>(void(Base::*)() && _Obj, Base * && _Arg1) Line 1573 C++ TestMain.exe!std::thread::_Invoke<std::tuple<void (__cdecl Base::*)(void),Base *>,0,1>(void * _RawVals) Line 56 C++ ucrtbased.dll() Unknown kernel32.dll() Unknown ntdll.dll() Unknown
即使将条件变量等待逻辑替换为简单的sleep语句:
std::this_thread::sleep_for(std::chrono::milliseconds(100));
程序依然会崩溃。
原因推测
目前推测崩溃由std::thread调用_Cnd_do_broadcast_at_thread_exit导致,但线程似乎并未成功启动,可能存在线程启动失败的情况。
内容的提问来源于stack exchange,提问作者thedemons
相关产品推荐
相关产品推荐

