背景
最近在移植已有C++11的项目到海思平台中,工程师反馈遇到了下面的报错
1 2 3 |
pure virtual method called terminate called without an active exception |
而且卡了好几天都没解决。CSDN上也有人反馈说没有解决,到底该如何解决呢?
排查
首先看看环境。使用的工具链是arm-hisiv600-linux
,其自身是gcc 4.9.4,板子是Hi3531D,CPU是A9核心。这里首先做了一个最简的例子编译并测试。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#include <iostream> #include <thread> int main() { std::thread thread_object([](){ std::cout << "print in thread" << std::endl; }); thread_object.join(); std::cout << "thread joined" << std::endl; return 0; } |
编译命令如下
1 2 |
arm-hisiv600-linux-gnueabi-g++ -o hello_cpp hello.cpp -std=c++11 -mcpu=cortex-a9 -mfpu=neon-fp16 |
编译出来一切正常,通过readelf确认下是否架构信息正确
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
$ readelf -a hello_cpp | grep Tag Tag_CPU_name: "Cortex-A9" Tag_CPU_arch: v7 Tag_CPU_arch_profile: Application Tag_ARM_ISA_use: Yes Tag_THUMB_ISA_use: Thumb-2 Tag_ABI_PCS_wchar_t: 4 Tag_ABI_FP_rounding: Needed Tag_ABI_FP_denormal: Needed Tag_ABI_FP_exceptions: Needed Tag_ABI_FP_number_model: IEEE 754 Tag_ABI_align_needed: 8-byte Tag_ABI_align_preserved: 8-byte, except leaf SP Tag_ABI_enum_size: int Tag_CPU_unaligned_access: v6 Tag_MPextension_use: Allowed Tag_Virtualization_use: TrustZone |
看出结果是没问题的,Cortex-A9 + armv7 + Thumb2
结果放到板子上跑却遇到了另一个报错
1 2 3 4 5 6 |
# ./hello_cpp terminate called after throwing an instance 'std::system_error' what(): Enable multithreading to use std::thread: Operation not permitted Aborted |
至少好像信息有些变化,我们再针对这个gcc4.9和std::thread的operation not permitted再搜索下看,结果直接就查到了这个链接,文中提到了加入”-thread”编译选项可以解决问题。
接下来我尝试了下新的编译命令
1 2 |
arm-hisiv600-linux-gnueabi-g++ -o hello_cpp hello.cpp -std=c++11 -thread -mcpu=cortex-a9 -mfpu=neon-fp16 |
编译完成后再次运行,就一切正常了。
分析
那为什么一开始gcc 4.9在编译带std::thread的时候不能正常启用pthread呢? 这可能是个bug,并且可以通过以下手段进行验证。对未加-pthread
编译出来的文件使用readelf查看其链接到的动态链接库,
1 2 3 4 5 6 |
$ readelf -d hello_cpp | grep "共享库" 0x00000001 (NEEDED) 共享库:[libstdc++.so.6] 0x00000001 (NEEDED) 共享库:[libm.so.6] 0x00000001 (NEEDED) 共享库:[libgcc_s.so.1] 0x00000001 (NEEDED) 共享库:[libc.so.6] |
发现其实不包含libpthread.so.0,其实这就是原因。从编译到链接都不包含线程库支持。
唉~真是坑啊