为什么嵌入式平台上无法正确实施Vtables?

7

我正在为一款嵌入式系统(特别是PSoC 5,使用PSoC Creator)开发代码,并使用C++编写。

虽然我已经克服了使用C ++的大部分障碍,首先是使用编译器标志-x c ++进行编译,定义new和delete运算符,并确保使用编译器标志-fno-exception不会抛出异常。然而,当涉及到使用虚函数时,我遇到了困境。

如果我尝试声明一个虚函数,编译器会给出错误信息undefined reference to "vtable for __cxxabiv1::__class_type_info"。唯一的解决方法是使用编译器标志-fno-rtti,这可以避免错误并使其成功编译。然而,如果我这样做,运行重载虚函数时嵌入式程序会崩溃,我认为这是因为vtable不存在。

我不明白为什么不能在嵌入式平台上使用虚函数,因为它只是成员对象之前或之后的内存中的额外空间(具体取决于编译器)。

我尝试使用虚函数的原因是因为我想在C++中使用FreeRTOS,其他人通过使用虚函数来实现了这一点(请参见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框架)。


2
你确定这是由于编译到嵌入式平台引起的吗?你尝试在标准平台上编译相关代码部分了吗? - jogojapan
PSoC IDE 在构建过程中运行链接器脚本。我已经包含了标志“-lstdc++”,以确保它链接到标准的 C++ 库。 - gbmhunter
我的直觉是问题出在我使用的编译顺序是为嵌入式平台设计的,而且代码是用C语言编写的,我可能缺少一个编译器标志或类似的东西,以便让GCC正确地使用G++。不,我还没有尝试在标准平台上进行编译。 - gbmhunter
不是直接的,但我想到的一个想法是,也许通过使用虚函数,你可以隐式地调用 dynamic_cast? - gbmhunter
我认为那样做不行。你可能在做一些棘手的事情,但是并不知道。你尝试过一个非常简单的例子吗?考虑这个片段。在我的托管平台上,这对我有效。在你的嵌入式平台上有效吗? - jxh
显示剩余6条评论
1个回答

11
错误信息中提到的类名 __cxxabiv1,表明您没有为平台链接正确的 C++ 运行时。我不了解 PSoC,但在更“正常”的平台上,如果在链接时使用了 gcc(或clang)命令而不是 g++(或clang++),或者在手动模糊情况下使用了 -lc++ 而没有使用 -stdlib=libc++ 或 -lstdc++ 而没有使用 -stdlib=libstdc++,则可能会发生此类错误。
使用 -v 选项检查链接器命令行,并尝试找出它正在拉取哪个 C++ 运行时库。它可能被命名为 libcxxabi 或 libcxxrt。
这位网友提供了逐步编译 PSoC Creator 中的 C++ 的说明;但他从未弄清楚如何链接 C++ 运行时库,因此他所有的提示都是关注如何从您的代码中移除 C++ 特性(-fno-rtti、-fno-exceptions 等)。我同意,在线上似乎没有任何有关如何实际使用 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
};
许多链接器能够通过命令行选项(如-C--defsym)将未定义符号定义为0x0。但这不仅是一个坏主意,而且也不方便,因为你必须弄清楚虚表对象的实际(重载)名称,而链接器没有告诉你。 (在GCC中,它可能类似于__ZTVN10__cxxabiv117__class_type_infoE。)
如果程序尝试使用虚表做任何事情,任何一种“解决方案”都会导致可怕的崩溃。但如果你只关心让链接器安静下来,并且知道程序永远不会使用RTTI,则可以使用-fno-rtti在整个项目中进行一致。
当你使用-fno-rtti时,具体会发生什么问题?

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