我可以在调用纯虚函数时禁用异常吗?

Eri*_*ric 6 c++ gcc

我有一些看起来像这样的代码:

class Writable {
public:
    virtual void putc(const char ch) = 0;
protected:
    virtual ~Writable() {};
};

class Readable {
public:
    virtual char getc() = 0;
protected:
    virtual ~Readable() {};
};
Run Code Online (Sandbox Code Playgroud)

注意两个虚函数.使用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
Run Code Online (Sandbox Code Playgroud)

使用方法存根替代纯虚函数再次运行它会产生:

arm-none-eabi-size  --format=berkeley bareCortexM.elf
   text    data     bss     dec     hex filename
  47340    2296     304   49940    c314 bareCortexM.elf
Run Code Online (Sandbox Code Playgroud)

这种巨大的差异似乎是由于例外.有什么方法可以防止这种情况发生吗?

Eri*_*ric 8

这篇博客文章对此进行了描述:在裸机上使用C++的较小二进制大小(g ++)

提供__cxa_pure_virtual()实施

如果您在任何地方使用纯虚函数但禁用了异常,您可能会注意到您的代码突然再次膨胀.

这发生在我身上,需要一段时间才能追踪,哎呀!
检查最终二进制文件的汇编列表(从objdump -h -C -S),看起来好像回来了!

我试过的一件事就是链接-nostdlib,完全将libstdc ++拉出图片.我提供了malloc,realloc,free和我使用过的一些其他stdlib函数的虚拟实现,但后来却avr32-g++ 抱怨我之前没见过的东西:我失踪了 __cxa_pure_virtual().

" 啊哈,"我想," 这必须是它!"在libstdc ++中找到的特定函数的源代码是一个调用 std::terminate(),在这里看到.那个电话在我可怜的AVR32的闪存中引发了一个可爱的派对,-fno-exceptions在他们的路上踩踏  .

无论如何,__cxa_pure_virtual()当你调用一个纯虚函数时,它实际上是被调用的.喜欢newdelete,这可能是你想要覆盖的东西,所以你自己的调试/跟踪代码可以给你有用的反馈.实现很简单,只要确保它extern "C"的名称不会被破坏:

extern "C" void __cxa_pure_virtual() { while(1); }
Run Code Online (Sandbox Code Playgroud)