You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基类构造函数启动纯虚派生线程后阻塞执行的未定义行为问题

实验性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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 23:10:33