c++ - 为什么 Vtables 在嵌入式平台上没有被正确实现?

标签 c++ compiler-construction embedded vtable freertos

我正在为嵌入式系统(特别是 PSoC 5,使用 PSoC Creator)开发代码,并使用 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,有关编写良好的文章,请参见 https://github.com/yuriykulikov/Event-driven_Framework_for_Embedded_Systems嵌入式 C++ FreeRTOS 框架)

最佳答案

错误消息引用名为 __cxxabiv1 的类这一事实表明您没有针对您的平台链接正确的 C++ 运行时。我对 PSoC 一无所知,但在更“正常”的平台上,如果您在链接中使用 gcc(resp. clang)命令,则可能会发生此类错误-time 而不是 g++(resp. clang++);或者在手动情况下如果你使用 -lc++ 没有 -stdlib=libc++-lstdc++ 没有 -stdlib=libstdc++ .

使用 -v 选项检查您的链接器命令行,并尝试找出它正在引入的确切 C++ 运行时库。它可能被命名为类似 libcxxabilibcxxrt

This guy here提供在 PSoC Creator 中编译 C++ 的分步说明;但他从未弄清楚如何链接到 C++ 运行时库,因此他的所有技巧都集中在如何从您的代码中删除 C++isms (-fno-rtti , -fno-exceptions,...).我同意网上似乎没有任何关于如何在 PSoC 中使用 C++ 的信息。

对于这个特定的错误,您总是可以尝试自己定义缺失的符号:

// 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
};

或者许多链接器能够通过命令行选项(例如-C--defsym)将 undefined symbol 定义为0x0。然而,这不仅是一个坏主意,而且也不方便,因为您必须弄清楚 vtable 对象的实际(损坏的)名称是什么,而链接器并没有告诉您。 (这是 GCC,它可能类似于 __ZTVN10__cxxabiv117__class_type_infoE。)

如果程序试图对 vtable 任何事情,这些“解决方案”中的任何一个都会导致可怕的崩溃;但是他们会关闭链接器,如果这就是您所关心的,并且您知道该程序永远不会真正使用 RTTI。但在那种情况下,在整个项目中始终如一地使用 -fno-rtti 就足够了。

当您使用 -fno-rtti 时,具体会出现什么问题?

关于c++ - 为什么 Vtables 在嵌入式平台上没有被正确实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16182365/

相关文章:

c - STM32CubeMX HAL_xxx_MspInit()函数中的MSP代表什么?

c++ - 将指针数组地址传递给函数并更新地址中的数据

android - 适用于 Android 的良好预建 GNU 工具链?

c - 将位域结构映射到 volatile 寄存器

c - 动态语义错误检查

c++ - 在 C(也许是 C++)中寻找数值/多媒体/信号处理基准

与嵌入式板交互的python脚本

c++ - 使用 SWIG 将 C++ char* 转换为 Java 中的 char[] 而不是 String

c++ - 将 std::bind 应用到带有参数 <boost::asio::ip::tcp::socket> 的函数时出错?

c++ - `std::optional::value` 中的 ref 限定成员函数有什么意义