使用std::function执行封装任务时触发SIGABRT,原因何在?
问题分析:执行std::packaged_task触发std::system_error异常
我希望用submit函数构造可在其他线程执行的任务,通过返回std::future避免阻塞,在合适时机获取结果。代码如下:
std::vector<std::function<void()>> fuctions(0); std::vector<std::future<int>> futures(0); template <typename Function, typename ...Args> std::future<typename std::result_of_t<Function(Args...)>> submit(Function f, Args... args) { using result_type = typename std::result_of_t<Function(Args...)>; std::function<result_type()> func = std::bind(std::forward<Function>(f), std::forward<Args>(args)...); auto task_ptr = std::make_shared<std::packaged_task<result_type()>>(func); std::function<void()> wrapper_fuc = [task_ptr]() { (*task_ptr)(); }; fuctions.push_back(wrapper_fuc); return task_ptr->get_future(); } int add(int a, int b) { return a + b; } int main() { futures.push_back(std::move(submit(add, 1, 2))); futures.push_back(std::move(submit(add, 2, 2))); futures.push_back(std::move(submit(add, 3, 2))); futures.push_back(std::move(submit(add, 4, 2))); futures.push_back(std::move(submit(add, 5, 2))); futures.push_back(std::move(submit(add, 6, 2))); futures.push_back(std::move(submit(add, 7, 2))); futures.push_back(std::move(submit(add, 8, 2))); std::cout << "do functions" << std::endl; for (int i = 0; i < fuctions.size(); ++i) { fuctions[i](); } std::cout << "functions done" << std::endl; for (int i = 0; i < futures.size(); ++i) { std::cout << "get result : " << futures[i].get() << std::endl; } }
执行fuctions[i]()时触发异常,信息如下:
terminate called after throwing an instance of 'std::system_error' what(): Unknown error -1 Program received signal SIGABRT, Aborted. __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50 50 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
原因分析
- 核心问题是编译时未链接pthread线程库。
- 虽然代码中没有显式创建线程,但
std::packaged_task和std::future属于C++标准库的线程组件,在Linux环境下依赖pthread库提供的底层支持。如果编译时未指定链接pthread,会导致运行时调用线程相关接口失败,抛出std::system_error(错误码-1对应底层线程资源调用失败)。
解决方案
- 在Linux下编译时添加
-pthread参数,例如:
g++ your_code.cpp -o your_program -std=c++14 -pthread
- 补充优化:代码中
typename std::result_of_t<...>的typename是多余的(std::result_of_t本身就是类型别名),建议移除以避免编译警告,修改后的submit函数:template <typename Function, typename ...Args> std::future<std::result_of_t<Function(Args...)>> submit(Function f, Args... args) { using result_type = std::result_of_t<Function(Args...)>; // ... 其余代码不变 }
内容的提问来源于stack exchange,提问作者peng zhang
相关产品推荐
相关产品推荐

