C++运行报错:terminate called after throwing an instance of ‘std::future_error‘(promise对象调用set前不能销毁!)
Posted Dontla
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++运行报错:terminate called after throwing an instance of ‘std::future_error‘(promise对象调用set前不能销毁!)相关的知识,希望对你有一定的参考价值。
文章目录
运行时报错信息
root@ubuntu:/userdata/20230201_test_cw_callback# ./a.out
Waiting for the greeting...
terminate called after throwing an instance of 'std::future_error'
what(): std::future_error: Broken promise
Aborted (core dumped)
root@ubuntu:/userdata/20230201_test_cw_callback#
错误代码
/*
这段代码实现了一个通过async_task函数执行线程中的函数,并通过std::promise对象将结果传递回主线程,最后使用std::future对象处理返回值。
*/
#include <iostream>
#include <thread>
#include <future>
#include <string>
#include <chrono>
template <typename Func, typename... Arg>
auto async_task(Func &&f, Arg &&...arg)
// 定义一个promise用于传递返回值
std::promise<decltype(f(arg...))> promise;
// 获取关联的future对象
auto future = promise.get_future();
// 创建线程
std::thread t([&promise, &f, &arg...]()
std::this_thread::sleep_for(std::chrono::seconds(2));
// 在线程中调用函数,并将返回值存储在promise中
promise.set_value(f(arg...));
);
//std::cout << future.get() << std::endl;
// 让主线程对线程进行管理
t.detach();
// 返回future对象
return future;
std::string get_greeting(std::string name)
return "Hello, " + name + "!";
int main()
auto greeting_future = async_task(get_greeting, "ChatGPT");
std::cout << "Waiting for the greeting..." << std::endl;
std::cout << greeting_future.get() << std::endl;
return 0;
/*
...的意思是可变参数,可以接受0个或多个参数。
&&的意思是引用折叠,表示函数可以接受任何类型的参数,如可以是左值也可以是右值。
写在arg前面表示函数能接受不定量的参数,而写在arg后面表示函数有一个可变参数,但是这个参数只能接受一个值。
*/
报错原因
不能用detach,因为async_task函数退出后,promise对象就被销毁了,销毁的对象去调用set_value,就会报Broken promise的错误,所以必须等待线程结束后,本函数再返回
解决办法
1、将上面代码中的detach改成join(但是这样做违背了异步回调的初衷)
/*
这段代码实现了一个通过async_task函数执行线程中的函数,并通过std::promise对象将结果传递回主线程,最后使用std::future对象处理返回值。
*/
#include <iostream>
#include <thread>
#include <future>
#include <string>
#include <chrono>
template <typename Func, typename... Arg>
auto async_task(Func &&f, Arg &&...arg)
// 定义一个promise用于传递返回值
std::promise<decltype(f(arg...))> promise;
// 获取关联的future对象
auto future = promise.get_future();
// 创建线程
std::thread t([&promise, &f, &arg...]()
std::this_thread::sleep_for(std::chrono::seconds(2));
// 在线程中调用函数,并将返回值存储在promise中
promise.set_value(f(arg...));
);
//std::cout << future.get() << std::endl;
// 让主线程对线程进行管理
//t.detach(); //不能用detach,因为本函数退出后,promise对象就被销毁了,销毁的对象去调用set_value,就会报Broken promise的错误,所以必须等待线程结束后,本函数再返回
t.join();
// 返回future对象
return future;
std::string get_greeting(std::string name)
return "Hello, " + name + "!";
int main()
auto greeting_future = async_task(get_greeting, "ChatGPT");
std::cout << "Waiting for the greeting..." << std::endl;
std::cout << greeting_future.get() << std::endl;
return 0;
/*
...的意思是可变参数,可以接受0个或多个参数。
&&的意思是引用折叠,表示函数可以接受任何类型的参数,如可以是左值也可以是右值。
写在arg前面表示函数能接受不定量的参数,而写在arg后面表示函数有一个可变参数,但是这个参数只能接受一个值。
*/
编译运行:
2、可以继续用detach(),但是需要用future.get()阻塞AsyncCallback函数返回
#include <iostream>
#include <future>
#include <thread>
#include <chrono>
int add(int a, int b)
return a + b;
template <typename Func, typename ...Arg>
auto AsyncCallback(Func&& f, Arg&& ...arg)
std::promise<int> promise;
std::future<int> future = promise.get_future();
std::thread t([&]()
int result = f(arg...);
promise.set_value(result);
);
//t.join();
t.detach(); //join和detach都可以,因为后面get()是阻塞的
//do something...
std::cout << "sleep_for(std::chrono::seconds(2))" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(2));
return future.get();
int main()
int result = AsyncCallback(add, 5, 10);
std::cout << "Result of add is: " << result << std::endl;
return 0;
编译运行结果:
参考文章:c++11多线程编程同步——使用future和promise
以上是关于C++运行报错:terminate called after throwing an instance of ‘std::future_error‘(promise对象调用set前不能销毁!)的主要内容,如果未能解决你的问题,请参考以下文章
C++11多线程运行报错:terminate called without an active exception(没有join或detach子线程)
C++11多线程运行报错:terminate called without an active exception(没有join或detach子线程)
gcc报错:terminate called after throwing an instance of ‘std::regex_error‘ what(): regex
gcc报错:terminate called after throwing an instance of ‘std::regex_error‘ what(): regex
gcc报错:terminate called after throwing an instance of ‘std::regex_error‘ what(): regex
gcc报错:terminate called after throwing an instance of ‘std::regex_error‘ what(): regex