C++:使用 packaged_task 的核心转储
Posted
技术标签:
【中文标题】C++:使用 packaged_task 的核心转储【英文标题】:C++: Core dump with packaged_task 【发布时间】:2017-01-22 11:33:42 【问题描述】:我从http://en.cppreference.com/w/cpp/thread/packaged_task 的一部分代码中复制了一个奇怪的核心转储,
#include <future>
#include <iostream>
#include <cmath>
void task_lambda()
std::packaged_task<int(int,int)> task([](int a, int b)
return std::pow(a, b);
);
std::future<int> result = task.get_future();
task(2, 9);
std::cout << "task_lambda:\t" << result.get() << '\n';
int main()
task_lambda();
我知道了
terminate called after throwing an instance of 'std::system_error'
what(): Unknown error -1
[1] 28373 abort (core dumped) ./a.out
调用栈如下:
#0 0x00007ffff71a2428 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54
#1 0x00007ffff71a402a in __GI_abort () at abort.c:89
#2 0x00007ffff7ae484d in __gnu_cxx::__verbose_terminate_handler() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3 0x00007ffff7ae26b6 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4 0x00007ffff7ae2701 in std::terminate() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5 0x00007ffff7ae2919 in __cxa_throw () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6 0x00007ffff7b0b7fe in std::__throw_system_error(int) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#7 0x0000000000404961 in std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) (__once=..., __f=<unknown type in /home/ace/test/a.out, CU 0x0, DIE 0x1246d>)
at /usr/include/c++/5/mutex:746
#8 0x0000000000403eb2 in std::__future_base::_State_baseV2::_M_set_result(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>, bool) (
this=0x61ec30, __res=..., __ignore_failure=false) at /usr/include/c++/5/future:387
#9 0x0000000000402b76 in std::__future_base::_Task_state<task_lambda()::<lambda(int, int)>, std::allocator<int>, int(int, int)>::_M_run(<unknown type in /home/ace/test/a.out, CU 0x0, DIE 0x17680>, <unknown type in /home/ace/test/a.out, CU 0x0, DIE 0x17685>) (this=0x61ec30, __args#0=<unknown type in /home/ace/test/a.out, CU 0x0, DIE 0x17680>,
__args#1=<unknown type in /home/ace/test/a.out, CU 0x0, DIE 0x17685>) at /usr/include/c++/5/future:1403
#10 0x00000000004051c1 in std::packaged_task<int (int, int)>::operator()(int, int) (this=0x7fffffffdca0, __args#0=2, __args#1=9) at /usr/include/c++/5/future:1547
#11 0x0000000000401c7d in task_lambda () at aa.cc:12
#12 0x0000000000401d1b in main () at aa.cc:19
然后我在我的程序中添加了一些示例代码,它变成了
#include <iostream>
#include <cmath>
#include <future>
#include <thread>
int f(int x, int y) return std::pow(x,y);
void task_thread()
std::packaged_task<int(int,int)> task(f);
std::future<int> result = task.get_future();
std::thread task_td(std::move(task), 2, 10);
task_td.join();
std::cout << "task_thread:\t" << result.get() << '\n';
void task_lambda()
std::packaged_task<int(int,int)> task([](int a, int b)
return std::pow(a, b);
);
std::future<int> result = task.get_future();
task(2, 9);
std::cout << "task_lambda:\t" << result.get() << '\n';
int main()
task_lambda();
错误消失了。即使我从未调用它,如何通过添加函数来更正程序?
gcc 版本
gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4)
用命令编译的程序:
g++ -std=c++11 aa.cc -lpthread
在@fedepad 的帮助下,我通过用 pthread 替换 lpthread 得到了正确的输出。 但我仍然混淆了第二个代码是如何通过添加一个虚拟函数来工作的!
【问题讨论】:
您能否尝试将以下标志-pthread
添加到您的编译行中,看看是否可以解决第一个版本?
我一直用-lpthread编译,没有这个标志会出现链接错误'/tmp/ccYGVXVs.o: In function std::thread::thread<std::packaged_task<int (int, int)>, int, int>(std::packaged_task<int (int, int)>&&, int&&, int&&)': /usr/include/c++/5/thread:137: undefined reference to
pthread_create' collect2: error: ld returned 1 exit status '
好像很像...gcc.gnu.org/bugzilla/show_bug.cgi?id=59830
尝试使用-pthread
而不是-lpthread
。你有什么不一样的吗?
@fedepad 是的,我得到了正常的输出。但是为什么添加一个 dummy 函数可以解决这个问题呢?
【参考方案1】:
我使用以下版本的 g++ 尝试了您的第一个代码 sn-p:
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
并编译如下
g++ -o test_threads test_threads.cpp -std=c++11 -pthread
我可以毫无问题地运行程序,并得到以下输出:
$ ./test_threads task_lambda: 512
如果我随后使用 -lpthread
就像您对以下内容所做的那样
g++ -o test_threads test_threads.cpp -std=c++11 -lpthread
我明白了
$ ./test_threads 在抛出“std::system_error”的实例后调用终止 what(): 未知错误 -1 [1] 7890 中止 ./test_threads
所以请使用-pthread
作为标志,而不是-lpthread
。
下面也提到了这种行为https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59830
-pthread
和 -lpthread
之间存在差异。
查看 g++ 的手册页
-pthread
使用 pthreads 库添加对多线程的支持。此选项为 preprocessor 和 linker 设置标志。
要查看两者都激活了哪些标志,可以检查以下内容:
g++ -dumpspecs | grep pthread
g++ -dumpspecs | grep lpthread
可以清楚地看到,如果使用-lpthread
,则有一些预处理器宏未激活。
【讨论】:
非常好的解决方案!我破解了我的代码半小时以找出"Unknown error -1"
的原因,并找到了解决我问题的答案!以上是关于C++:使用 packaged_task 的核心转储的主要内容,如果未能解决你的问题,请参考以下文章
Visual Studio 中的 std::packaged_task 错误?
将 packaged_task 对象移动到 lambda 捕获时出错