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

静态初始化jthread调用std::stacktrace_entry::description时发生死锁

单例线程退出时死锁问题

以下C++代码在退出main()函数时会发生死锁:

#include <stacktrace>
#include <iostream>
#include <thread>
#include <semaphore>
#include <chrono>

using namespace std::chrono_literals;

struct Singleton
{
    Singleton()
    {
        worker = std::jthread{ [this] {
            sema.acquire();
            for (auto& e : trace) {
                std::this_thread::sleep_for(50ms);
                std::cout << e.description() << std::endl;
            }
        } };
    }
    std::binary_semaphore sema{ 0 };
    std::stacktrace trace;
    std::jthread worker;
};

std::stacktrace g()
{
    return std::stacktrace::current();
}

std::stacktrace f()
{
    return g();
}

Singleton& get()
{
    static Singleton sing;
    return sing;
}

int main(int argc, char** argv) {
    get().trace = f();
    get().sema.release();
    std::this_thread::sleep_for(350ms);
    return 0;
}

具体表现为,调用description()时,CRT代码尝试获取临界区时发生死锁。

我推测description()会调用依赖CRT全局对象的代码,而这些对象由临界区管理。可能的原因有两个:

  • 该全局对象在std::jthread析构函数执行前,就随main退出被销毁了;
  • 退出main时,主线程和工作线程同时进入了同一个临界区。

想请教这段代码中哪部分用法导致了未定义行为(UB)?

背景说明:
这是从一个大型代码库中提炼的最小复现案例,原代码库中用单例管理包含工作线程和无锁队列的日志通道对象。

编辑说明:
代码中的sleep_for仅用于演示,并非必需,也不是为了修复竞态条件。即使移除这些调用,死锁现象依然存在。

内容的提问来源于stack exchange,提问作者chili

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 09:05:16