我正在为嵌入式系统(特别是 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++ 运行时库。它可能被命名为类似 libcxxabi
或 libcxxrt
。
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/