我正在为嵌入式系统(特别是使用PSoC Creator的PSoC 5)开发代码,并用C++编写。
虽然我克服了使用C++的大部分障碍,但首先使用编译器标记-x c++
在C++中进行编译,定义了new和delete运算符,确保编译器标记-fno-exception
不引发异常,但我遇到了麻烦在使用虚函数时。
如果我尝试声明一个虚函数,则编译器会给我错误undefined reference to "vtable for __cxxabiv1::__class_type_info"
。解决此问题的唯一方法是使用编译器标志-fno-rtti
,它可以防止错误并使其成功编译。但是,如果这样做,则嵌入式程序在尝试运行重载的虚拟函数时会崩溃,并且我认为这是因为vtable不存在。
我不明白为什么您不应该在嵌入式平台上实现vtable,因为所有这些都是成员对象之前或之后内存中的额外空间(取决于确切的编译器)。
我尝试使用虚拟函数的原因是因为我想将FreeRTOS与C++一起使用,其他人已经通过使用虚拟函数实现了这一点(有关讨论,请参见http://www.freertos.org/FreeRTOS_Support_Forum_Archive/July_2010/freertos_Is_it_possible_create_freertos_task_in_c_3778071.html,有关编写良好的嵌入式C++ FreeRTOS框架,请参见https://github.com/yuriykulikov/Event-driven_Framework_for_Embedded_Systems)。
最佳答案
错误消息引用名为__cxxabiv1
的类的事实表明您未针对平台使用正确的 C++运行时进行链接。我对PSoC一无所知,但是在更多的“正常”平台上,如果您在链接时使用gcc
(resp。clang
)命令而不是g++
(resp。clang++
)命令,可能会发生这种错误。或在随波逐流的情况下,如果您使用的-lc++
不带-stdlib=libc++
或-lstdc++
不带-stdlib=libstdc++
。
使用-v
选项检查您的链接器命令行,并尝试准确找出要引入的C++运行时库。它可能会被命名为libcxxabi
或libcxxrt
。
This guy here给出了在PSoC Creator中编译C++的分步说明;但是他从来没有想过如何与C++运行时库链接,因此他的所有技巧都集中在如何从代码(-fno-rtti
,-fno-exceptions
,...)中删除C++形式。我同意在线上似乎没有有关如何将C++与PSoC一起实际使用的任何信息。
对于此特定错误,您始终可以尝试自己定义缺少的符号:
// file "fix-link-errors.cpp"
namespace __cxxabiv1 {
class __class_type_info {
virtual void dummy();
};
void __class_type_info::dummy() { } // causes the vtable to get created here
};
或者许多链接器都可以通过命令行选项(例如
0x0
或-C
)将 undefined symbol 定义为--defsym
。但是,这不仅是一个坏主意,而且很不方便,因为您必须弄清楚vtable对象的实际(混杂的)名称是什么,而链接程序却没有告诉您。 (这是GCC,可能类似于__ZTVN10__cxxabiv117__class_type_infoE
。)如果程序尝试对vtable进行任何操作,则这些“解决方案”中的任何一个都将导致可怕的崩溃;但是如果您关心的只是这些,他们就会关闭链接器,并且您知道该程序将永远不会真正使用RTTI。但是在那种情况下,在整个项目中一致地使用
-fno-rtti
应该足够了。具体来说,当您使用
-fno-rtti
时出了什么问题?