纯虚方法调用——交叉编译
-
20-12-2019 - |
题
我正在编写一个用于 BeagleBone Black 的基于事件的编程库,但遇到了一个奇怪的错误。
当我使用完全相同的标志编译完全相同的代码时,我在基于 ARM 的处理器上收到以下错误,但当我运行为 x86 计算机编译的代码时则不会。
$ ./missionControl
pure virtual method called
pure virtual method called
pure virtual method called
terminate called recursively
terminate called recursively
Aborted
当我在笔记本电脑上编译并运行时, 程序正确运行.
这是我用来编译的命令(实际上,我使用的是 Makefile,但是两种编译方法都表现出完全相同的行为):
g++ -std=gnu++11 -pthread -O3 -D_GLIBCXX_USE_NANOSLEEP -o missionControl `find . -name *.cpp`
是否与 Ubuntu 交叉编译并不重要 arm-linux-gnueabi-g++
或 ARM 兼容 g++
在实际的 BeagleBone 上,我仍然在 ARM 上遇到错误。
我的问题是这样的:可能是什么原因导致此错误,我该怎么做才能找到根源?对于相同版本的 G++,为什么这种情况会发生在一种处理器架构上,而不是另一种处理器架构上?
谢谢!
以下是来自 ARM 处理器 GDB 的回溯:
#0 0xb6d4adf8 in raise () from /lib/libc.so.6
#1 0xb6d4e870 in abort () from /lib/libc.so.6
#2 0xb6f50ab4 in __gnu_cxx::__verbose_terminate_handler() () from /usr/lib/libstdc++.so.6
#3 0xb6f4ea4c in ?? () from /usr/lib/libstdc++.so.6
#4 0xb6f4ea4c in ?? () from /usr/lib/libstdc++.so.6
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
解决方案
事实证明,该问题是由于 BeagleBone 上运行的 ARM 版本的 libstdc++ 中的错误所致。创建 std::thread 时,根本没有虚拟函数的小玩具程序会导致相同的错误(“调用纯虚拟函数”)。
我将尝试在 BeagleBone 本身上编译 gcc/libstdc++ 4.8 的自定义版本 - 即使这需要很长时间。
其他提示
这 纯虚方法调用 当您在构造实现该函数的派生类型之前或在该函数已被析构之后尝试使用动态分派来调用基类中的纯虚函数时,会发生错误。
最常见的原因是基类尝试通过构造函数或析构函数调用此级别的纯虚函数。除此之外,正如一些评论中指出的那样,如果您尝试访问死对象,您也可能会遇到同样的问题。
只需将调试器附加到程序中,即可查看调用了哪些虚函数以及从何处调用。
看: https://groups.google.com/forum/#!topic/automatak-dnp3/Jisp_zGhd5I
和: 为什么这个简单的 c++11 线程示例在使用 clang 3.2 编译时会失败?
现在,我不知道为什么这会起作用,但至少对我来说是这样。将以下四个预处理器定义添加到编译器命令行:
__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
我还没有尝试过看看它们是否都是必需的,或者是否可以只使用其中一些。但这为我解决了问题。感谢那些写下上述答案的人,也感谢我的同事在谷歌上搜索了我:)