【问题标题】:ARM C++ newlibnano: Pure virtual function causes linker errorARM C++ newlibnano:纯虚函数导致链接器错误
【发布时间】: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?) 的虚拟表中引用了一个错误处理程序,而这可能间接引用了您的库未提供的缺失函数。
  • 你可能想看看stackoverflow.com/a/9355553
  • 我的嫌疑人也是__cxa_pure_virtual;如果您的库将其定义为弱符号,您可以只定义不需要上述符号的自定义实现。 OTOH,您也可以为那些丢失的符号定义一些存根 - 使 killsbrk 总是失败(errno=ENOSYS),并且 exit 挂在一个紧密的循环中(可能在低功耗模式下)。

标签: c++ inheritance gcc arm virtual


【解决方案1】:

纯虚方法需要异常支持,因为有时可以调用它们。需要缺少的库函数来实现异常处理。 查看相关问题here

【讨论】:

  • 谢谢你的建议,但你误解了我的问题:(请看我的编辑,我附上了一个简单的例子。
  • 是的,我以为我说的是显而易见的,谢谢你的澄清。改变了整个答案。您忘记在示例代码中将 Child 声明为 Parent 的子类,顺便说一句。
  • 调用纯虚函数不会抛出异常;异常处理与此无关(虽然可能与纯虚函数调用错误处理程序的默认实现有关)。
  • 你是对的。大多数纯虚函数错误处理程序只是简单地终止程序而不产生异常。但是,很明显 klasyc 使用的运行时中的处理程序不需要,因为如果这样做,它真的不需要所有这些附加功能。但也有可能处理程序是在一个模块中实现的,该模块引用了所有这些库函数以获得不相关的功能。
  • 实际上我想说_exit_kill 是直接终止程序的处理程序的最佳选择;低级动态内存分配一般需要sbrk,这有点奇怪,但对于它的支持功能来说并不完全牵强。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-01
  • 1970-01-01
  • 2018-06-23
  • 2011-06-04
  • 1970-01-01
相关资源
最近更新 更多