6

私はこのように見えるいくつかのコードを持っています:

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

class Readable {
public:
    virtual char getc() = 0;
protected:
    virtual ~Readable() {};
};

2つの仮想関数に注目してください。を使用してこれを(他のコードと一緒に)コンパイルし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

この大きな違いは、例外によるものと思われます。これを防ぐ方法はありますか?

4

2 に答える 2

8

これは、このブログ投稿で説明されています:ベアメタル(g ++)上のC++でのより小さなバイナリサイズ

__cxa_pure_virtual()実装を提供する

どこでも純粋仮想関数を使用しているが、例外を無効にしている場合、コードが突然再び膨らむことに気付くかもしれません。

これは私に起こりました、そして、おっと、追跡するのに時間がかかりました!
(からの)最終バイナリのアセンブリリストをobjdump -h -C -S調べると、例外が戻ってきているように見えました!

私が試したことの1つは、とリンクして-nostdlib、libstdc++を画像から完全に引き出すことでした。私はmalloc、realloc、free、および使用した他のいくつかのstdlib関数のダミー実装を提供しましたが、それからavr32-g++ 私が前に見たことがない何かについて不平を言いました:私は行方不明 でした__cxa_pure_virtual()

「<em>ああ」と私は思いました。「<em>これはそれでなければなりません!」libstdc ++にあるその特定の関数のソースには、ここにあるへの呼び出しが std::terminate()あります。その呼び出しは、私の貧弱なAVR32のフラッシュメモリのいたるところに素敵なパーティーを投げかけ、 -fno-exceptions途中で踏みにじりました。

とにかく、__cxa_pure_virtual()純粋仮想関数を呼び出すときに実際に呼び出されるのはこれです。と同様newdelete、これはおそらくとにかくオーバーライドしたいものなので、独自のデバッグ/トレースコードで有用なフィードバックを得ることができます。extern "C"実装は簡単です。名前が壊れないように、必ず作成してください。

extern "C" void __cxa_pure_virtual() { while(1); }
于 2013-02-04T15:12:08.310 に答える
0

同じ問題が発生しましたが、 __cxa_pure_virtualを実装しても役に立ちません。

しかし、私にとっての解決策は、-fno-exceptionsオプションの横に-fno -rttiを追加することでした。

于 2014-09-08T10:44:14.660 に答える