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

std::promise<void>抛出未知错误,添加零时长sleep为何可规避?

为什么GCC 4.8/5.4中std::promise直接操作会抛异常,加0时长sleep就正常?

这个问题我刚好了解过,本质是早期GCC版本里libstdc++的一个和线程库初始化相关的小bug,咱们一步步拆解清楚:

问题重现

你给出的第一段代码在GCC 4.8.5和5.4.0下编译运行会抛出std::system_error:

#include <future>
#include <thread>
int main() {
 std::promise<void> p;
 p.set_value();
 p.get_future().get();
 return 0;
}

编译运行命令:

$ g++ -o foo foo.cpp -std=c++11 -lpthread
$ ./foo
terminate called after throwing an instance of 'std::system_error'
what(): Unknown error -1

而添加零时长sleep后,程序就能正常运行无异常:

int main() {
 std::this_thread::sleep_for(std::chrono::milliseconds(0));
 std::promise<void> p;
 p.set_value();
 p.get_future().get();
 return 0;
}

核心原因

这个现象的根源在于旧版本libstdc++中线程库的初始化时机问题:

  • std::promise和std::future的实现依赖pthread库的同步原语(比如互斥锁、条件变量)。
  • 主线程启动时,pthread库的初始化并不是完全同步完成的。当你在main函数最开头直接操作std::promise时,pthread库的某些关键内部结构还没初始化好,导致底层同步调用失败,最终抛出std::system_error(错误码-1对应底层pthread调用返回的未初始化错误)。

为什么零时长sleep能解决问题?

std::this_thread::sleep_for哪怕是0毫秒的睡眠,其底层实现也会调用pthread的相关函数(比如pthread_cond_timedwait)。这些函数会触发pthread库的完整初始化流程,确保所有必要的内部结构都已准备就绪。等后续再创建std::promise并执行操作时,依赖的同步机制已经正常工作,自然就不会抛出异常了。

后续解决方案

这个bug在GCC 6及以上的版本中已经被彻底修复,如果你能升级到更高版本的GCC,就不需要再用这种临时的workaround了。如果必须使用旧版本,除了添加零时长sleep,也可以在程序开头手动触发线程库初始化(比如创建一个临时线程再销毁,或者调用pthread_once),效果是一样的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:59:22