为啥从主线程调用时,`std::promise::set_value` 会抛出错误?

Posted

技术标签:

【中文标题】为啥从主线程调用时,`std::promise::set_value` 会抛出错误?【英文标题】:Why does `std::promise::set_value` throw an error when invoked from the main thread?为什么从主线程调用时,`std::promise::set_value` 会抛出错误? 【发布时间】:2021-03-16 14:15:36 【问题描述】:

当我运行以下代码时,

#include <future>

int main()

    std::promise<int> p;
    p.set_value(1);
    return 0;

std::system_error 被抛出。但是,当我在另一个线程中设置 promise 的值时,

#include <future>
#include <thread>

int main()

    std::promise<int> p;
    std::thread([&]p.set_value(1);).join();
    return 0;

一切正常。根据我对std::promise 的了解,调用set_value 不应该抛出异常,除非promise 没有共享状态(即它已被移出)或者已经为其分配了一个值,即使那样它也会抛出@ 987654329@,而不是std::system_error。由于没有数据竞争或任何类似的事情,我是从创建承诺的线程还是在另一个线程中调用 set_value 都无关紧要。我有什么遗漏吗?

我用 g++clang 都试过了,结果相同。具体来说,当我在顶部运行代码时,将以下内容输出到stderr

terminate called after throwing an instance of 'std::system_error'
  what():  Unknown error -1
Aborted (core dumped)

这些命令用于编译顶部的代码,

g++ main_thread.cpp -o main_thread -std=c++17 -g -Og
clang main_thread.cpp -o main_thread -std=c++17 -lstdc++

这些用于编译底部的代码:

g++ separate_thread.cpp -o separate_thread -lpthread -std=c++17 -g -Og
clang separate_thread.cpp -o separate_thread -std=c++17 -lstdc++ -lpthread

【问题讨论】:

@MarekR 考虑this verbatim reproduction。 @IsaacSaffold 默认构造的承诺也没有共享状态:en.cppreference.com/w/cpp/thread/promise/promise 哦,等等。它是空的,不是没有。不确定了。 哦。当我使用-pthread 而不是-lpthread 时,它可以工作。我查看了g++ 的手册页,显然前者是链接它的正确方法。而@JDługosz,回溯是难以理解的。它们都是具有多个参数和名称的函数模板,每个模板跨越几行。 相关Difference between -pthread and -lpthread while compiling 【参考方案1】:

std::promise 是Thread Support Library 的一部分,因此它需要在您的编译器选项中启用线程支持(例如-pthread)。

请注意,-pthread 会影响编译和链接阶段。来自man g++

-pthread 使用 pthreads 库添加对多线程的支持。此选项为预处理器和链接器设置标志。

【讨论】:

您会认为在这种情况下会引发链接器错误,但我认为它不会发生。 编辑添加了为什么 -pthread 不仅仅是一个链接器选项

以上是关于为啥从主线程调用时,`std::promise::set_value` 会抛出错误?的主要内容,如果未能解决你的问题,请参考以下文章

带有 std::promise 的 C++11 分段错误

C++ std::future与promise(异步回调异步调用)

C++ std::future与promise(异步回调异步调用)

为啥 MinGW 中仍然没有 std::thread、std::promise 和 std::future? win32中promise和futures的替代方案是啥?

C11线程管理:异步操作

C++ 线程