我正在为嵌入式系统(特别是使用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++运行时库。它可能会被命名为libcxxabilibcxxrt

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时出了什么问题?

09-06 18:38