__cxa_pure_virtual的目的是什么?

66

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

undefined reference to `__cxa_pure_virtual'

我发现了这份文档,其中声明:

__cxa_pure_virtual函数是一个错误处理程序,当调用纯虚函数时将被调用。

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

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

按照建议定义此函数可以解决错误,但我想知道:

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

8
在使用gcc命令时,如果您应该使用g++命令,就可能会出现此错误;我至少犯过一次这样的错误 :) - user2023370
2个回答

46

如果在程序运行时创建一个对象时,其虚函数指针未填充,并且调用相应的函数时,则会调用“纯虚函数”。

您所描述的处理程序应定义在与开发环境一起提供的默认库中。如果您不小心遗漏了默认库,您会发现该处理程序未定义:链接器看到声明但没有定义。这时您需要提供自己的版本。

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


什么原因会导致虚函数指针没有被填充?编译器不会检测到并防止编译吗? - Matthew Murdoch
1
@xtofl 谢谢,https://dev59.com/gXVD5IYBdhLWcg3wE3Ro 对我很有帮助。 - Matthew Murdoch

29

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()编写成无限循环是可以接受的?

这至少是安全的,它会执行可预测的操作。将程序终止并报告错误会更有用。但是,无限循环会很难调试,除非您拥有能够中断执行并提供堆栈回溯的调试器。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接