纯虚拟方法称为 - 交叉编译

Pure virtual method called - cross compiling

本文关键字:交叉编译 虚拟 方法      更新时间:2023-10-16

我正在编写一个基于事件的编程库,用于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++ 交叉编译,还是在实际的 Beaglebone 上与 ARM 兼容的g++交叉编译,我仍然会在 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 的自定义版本 - 即使这需要很长时间。

当您尝试使用动态调度在构造实现该函数的派生类型之前或已销毁之后调用基中的纯虚拟函数时,会发生称为 error 的纯虚拟方法

最常见的原因是基类尝试通过构造函数或析构函数调用在此级别纯的虚函数。除此之外,正如一些评论中指出的那样,如果您尝试访问死对象,您也可能会遇到同样的问题。

只需将调试器附加到程序,即可查看虚拟函数的名称和从何处调用。

参见: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

我还没有尝试过看看它们是否都是必需的,或者你是否可以只逃脱一些。但这为我解决了问题。感谢那些写了上述答案的人,感谢我的同事在谷歌上搜索了我:)