64

在使用 avr-gcc 进行编译时,我遇到了如下链接器错误:

undefined reference to `__cxa_pure_virtual'

我发现这个文件说:

__cxa_pure_virtual函数是在调用纯虚函数时调用的错误处理程序。

如果您正在编写具有纯虚函数的 C++ 应用程序,则必须提供自己的__cxa_pure_virtual错误处理函数。例如:

extern "C" void __cxa_pure_virtual() { while (1); }

按照建议定义此函数可修复错误,但我想知道:

  • 这个函数的目的是什么,
  • 为什么我需要自己定义它和
  • 为什么将其编码为无限循环是可以接受的?
4

2 回答 2

45

如果在程序运行时的任何地方创建了一个未填充虚函数指针的对象,并且当调用相应的函数时,您将调用一个“纯虚函数”。

您描述的处理程序应该在您的开发环境附带的默认库中定义。如果您碰巧省略了默认库,您会发现这个处理程序未定义:链接器看到一个声明,但没有定义。那时您需要提供自己的版本。

无限循环是可以接受的,因为它是一个“响亮”的错误:您的软件的用户会立即注意到它。任何其他“响亮”的实现也是可以接受的。

于 2009-05-28T12:02:23.963 回答
26

1) __cxa_pure_virtual() 函数的目的是什么?

在对象构造/销毁期间可以调用纯虚函数。如果发生这种情况,会调用 __cxa_pure_virtual() 来报告错误。请参阅“纯虚函数调用”崩溃从何而来?

2)为什么你需要自己定义它?

通常这个函数由 libstdc++ 提供(例如在 Linux 上),但 avr-gcc 和 Arduino 工具链不提供 libstdc++。

Arduino IDE 在构建某些程序时设法避免链接器错误,因为它使用选项“-ffunction-sections -fdata-sections”进行编译并使用“-Wl,--gc-sections”链接,这会删除对未使用符号的一些引用.

3) 为什么将 __cxa_pure_virtual() 编码为无限循环是可以接受的?

好吧,这至少是安全的;它做了一些可预测的事情。中止程序并报告错误会更有用。但是,无限循环很难调试,除非您有一个可以中断执行并提供堆栈回溯的调试器。

于 2012-02-20T02:38:25.270 回答