我有一些看起来像这样的代码:
class Writable {
public:
virtual void putc(const char ch) = 0;
protected:
virtual ~Writable() {};
};
class Readable {
public:
virtual char getc() = 0;
protected:
virtual ~Readable() {};
};
注意两个虚函数。使用arm-none-eabi-gcc
编译它(以及我的其他代码),并与-fno-exceptions
链接产生此输出:
arm-none-eabi-size --format=berkeley bareCortexM.elf
text data bss dec hex filename
108948 2304 2372 113624 1bbd8 bareCortexM.elf
使用方法存根替代纯虚函数再次运行它会产生:
arm-none-eabi-size --format=berkeley bareCortexM.elf
text data bss dec hex filename
47340 2296 304 49940 c314 bareCortexM.elf
这种巨大的差异似乎是由于例外。有什么办法可以防止这种情况发生吗?
答案 0 :(得分:8)
此博客文章描述了这一点:Smaller binary size with C++ on baremetal (g++)
提供
__cxa_pure_virtual()
实施如果您在任何地方使用纯虚函数但禁用了异常,则可以 注意你的代码突然再次膨胀。
这发生在我身上,需要一段时间才能追踪,哎呀! 检查最终二进制文件的汇编列表(来自
objdump -h -C -S
),它看起来像异常 回来了!我试过的一件事就是与
-nostdlib
联系,完全拉出了libstdc ++ 图片。我提供了malloc,realloc的虚拟实现, free,以及我使用的一些其他stdlib函数,但随后avr32-g++
抱怨我以前没见过的东西:我失踪了__cxa_pure_virtual()
。“ Aha ,”我想,“这必须是它!”来源于此 在libstdc ++中找到的特定函数是对它的调用
std::terminate()
,seen here。那个电话在我可怜的AVR32上引起了一场可爱的聚会 闪存,在进入-fno-exceptions
时踩踏。无论如何,
__cxa_pure_virtual()
是您实际被调用的内容 调用纯虚函数。与new
和delete
一样, 这可能是你想要覆盖的东西,所以你自己 调试/跟踪代码可以为您提供有用的反馈。实施是 直截了当,只要确保它extern "C"
,所以名称不会被破坏:extern "C" void __cxa_pure_virtual() { while(1); }
答案 1 :(得分:0)
我遇到了同样的问题,但实施 __ cxa_pure_virtual 并没有帮助我。
但我的解决方案是在 -fno-exceptions 选项旁添加 -fno-rtti 。