【发布时间】:2018-01-30 20:24:13
【问题描述】:
我正在使用 arm-none-eabi-g++ 版本 4.9.3 为 ARM Cortex M4 编译嵌入式应用程序。为了使目标图像尽可能小,我将应用程序链接到-specs=nano.specs。
现在我遇到了一个奇怪的问题:当我在代码的任何地方定义一个纯虚函数(然后我在子类中定义它的主体)时,我得到这个链接错误:
abort.c:-1: Error: undefined reference to `_exit'
sbrkr.c:-1: Error: undefined reference to `_sbrk'
signalr.c:-1: Error: undefined reference to `_kill'
...
这是正确的,因为我真的没有在我的项目中定义这些函数,因为我根本不使用它们。但是当我想制作一个纯虚函数时,为什么编译器需要这些函数呢?当我为虚函数定义一个空体时,链接器错误就消失了。有人能解释一下纯虚函数背后的魔力吗?
编辑:为了让事情更清楚,这是我的代码的一个非常简单的示例:
class Parent {
public:
virtual int foo() { return -1; } // This compiles normally.
virtual int foo() = 0; // This gives me the linker error above.
}
class Child {
public:
virtual int foo { return 42; }
}
Child test;
【问题讨论】:
-
我们能看到导致问题的代码吗?它是否特定于带有您提到的标志的这个环境 - 没有它它可以编译?
-
对不起,代码是相当大的项目的一部分,很难分享。该错误特定于微控制器,因为它们不使用标准 libc,它定义了上面链接器错误中提到的功能。有几个版本的微控制器 libc,它们在包含的功能数量和占用空间方面有所不同。我正在使用最小的版本,它没有定义链接器错误中提到的函数。但是我不明白为什么我需要这些函数来定义一个纯虚函数。
-
我的猜测如下:编译器从抽象类 (
__cxa_pure_virtual?) 的虚拟表中引用了一个错误处理程序,而这可能间接引用了您的库未提供的缺失函数。 -
我的嫌疑人也是
__cxa_pure_virtual;如果您的库将其定义为弱符号,您可以只定义不需要上述符号的自定义实现。 OTOH,您也可以为那些丢失的符号定义一些存根 - 使kill和sbrk总是失败(errno=ENOSYS),并且exit挂在一个紧密的循环中(可能在低功耗模式下)。
标签: c++ inheritance gcc arm virtual