Avr-gccでコンパイルしているときに、次のようなリンカーエラーが発生しました。
_undefined reference to `__cxa_pure_virtual'
_
このドキュメント を見つけました:
_
__cxa_pure_virtual
_関数は、純粋な仮想関数が呼び出されたときに呼び出されるエラーハンドラーです。純粋な仮想関数を持つC++アプリケーションを作成する場合は、独自の_
__cxa_pure_virtual
_エラーハンドラー関数を提供する必要があります。例えば:
extern "C" void __cxa_pure_virtual() { while (1); }
この関数を提案どおりに定義するとエラーが修正されますが、知りたいのは次のとおりです。
プログラムのランタイムのどこかに、仮想関数ポインタが設定されていない状態でオブジェクトが作成され、対応する関数が呼び出されると、「純粋な仮想関数」が呼び出されます。
説明するハンドラは、開発環境に付属するデフォルトのライブラリで定義する必要があります。デフォルトのライブラリを省略すると、このハンドラーは未定義になります。リンカーは宣言を参照しますが、定義は参照しません。独自のバージョンを提供する必要があるときです。
無限ループは「大きな」エラーであるため許容できます。ソフトウェアのユーザーはすぐに気づくでしょう。他の「騒々しい」実装も受け入れられます。
1)関数__cxa_pure_virtual()の目的は何ですか?
純粋な仮想関数は、オブジェクトの構築/破棄中に呼び出すことができます。その場合、__ cxa_pure_virtual()が呼び出されてエラーが報告されます。 「純粋な仮想関数呼び出し」のクラッシュはどこから来ますか? を参照してください。
2)なぜ自分で定義する必要があるのですか?
通常、この関数はlibstdc ++(たとえばLinux)によって提供されますが、avr-gccとArduinoツールチェーンはlibstdc ++を提供しません。
Arduino IDEは、オプション「-ffunction-sections -fdata-sections」および「-Wl、-gc-sections」を使用してリンクするため、一部のプログラムをビルドするときにリンカーエラーを回避できます。 "、未使用のシンボルへの参照を削除します。
3)__cxa_pure_virtual()を無限ループとしてコーディングするのはなぜ受け入れられるのですか?
まあ、これは少なくとも安全です。予測可能なことを行います。プログラムを中止してエラーを報告する方が便利です。ただし、実行を中断してスタックのバックトレースを提供できるデバッガーがない限り、無限ループはデバッグするのが面倒です。