これはOS開発サイトからの中古の質問ですが、どこにもきちんとした説明が見つからなかったので、興味をそそられました。
Gccを使用して独立したC++プログラムをコンパイルおよびリンクすると、次のようなリンカーエラーが発生する場合があります。
out/kernel.o:(.eh_frame+0x11): undefined reference to `__gxx_personality_v0'
これは明らかに、このシンボルはlibstdc ++で定義されているためです。libstdc++は独立した環境にはありません。問題を解決するには、このシンボルをどこかで定義する必要があります。
void *__gxx_personality_v0;
どちらがいいのですが、魔法のように機能するものが好きではありません。
これは、スタック非表示テーブルで使用されます。これは、たとえば 別の質問への回答 のアセンブリ出力で確認できます。その答えで述べたように、その使用は Itanium C++ ABI で定義されており、 Personality Routine と呼ばれています。
グローバルなNULL voidポインターとして定義することで「機能する」のは、おそらく例外がスローされないためです。何かが例外をスローしようとすると、それが正しく動作しないことがわかります。
もちろん、例外を使用しているものがない場合は、-fno-exceptions
を使用して無効にすることができます(RTTIを使用していない場合は、-fno-rtti
を追加することもできます)。それらを使用している場合は、(既に述べた他の回答として)gcc
の代わりにg++
でリンクする必要があります。これにより-lstdc++
が追加されます。
これは例外処理の一部です。 gcc EHメカニズムにより、さまざまなEHモデルを混在させることができ、パーソナリティルーチンが呼び出されて、例外の一致、起動するファイナライズなどを決定します。この特定のパーソナリティルーチンは、Cgc例外処理)。
例外処理は、独立した実装に含まれています。
この理由は、おそらくgcc
を使用してコードをコンパイルするためです。オプション-###
を指定してコンパイルすると、リンカープロセスを呼び出すときにリンカーオプション-lstdc++
が欠落していることがわかります。 g++
を指定してコンパイルすると、そのライブラリが含まれ、そのために定義されたシンボルが含まれます。
libstd++
コードベースの簡単なgrepにより、__gx_personality_v0
の次の2つの使用法が明らかになりました。
Libsupc ++/unwind-cxx.hで
// GNU C++ personality routine, Version 0.
extern "C" _Unwind_Reason_Code __gxx_personality_v0
(int, _Unwind_Action, _Unwind_Exception_Class,
struct _Unwind_Exception *, struct _Unwind_Context *);
Libsupc ++/eh_personality.ccに
#define PERSONALITY_FUNCTION __gxx_personality_v0
extern "C" _Unwind_Reason_Code
PERSONALITY_FUNCTION (int version,
_Unwind_Action actions,
_Unwind_Exception_Class exception_class,
struct _Unwind_Exception *ue_header,
struct _Unwind_Context *context)
{
// ... code to handle exceptions and stuff ...
}
(注:実際にはそれよりも少し複雑です。詳細を変更できる条件付きコンパイルがあります)。
したがって、コードが実際に例外処理を使用していない限り、シンボルをvoid*
として定義しても何にも影響しませんが、すぐにクラッシュします-__gxx_personality_v0
はグローバルオブジェクトではなく関数なので、関数を呼び出そうとすると、アドレス0にジャンプしてセグメンテーション違反が発生します。
私は一度このエラーがあり、Originを見つけました:
私はgccコンパイラを使用しており、C++プログラムではなくCプログラムを実行していたにもかかわらず、ファイルはCLIENT.C
と呼ばれていました。
gccは.C
拡張をC++プログラムとして、.c
拡張をCプログラムとして認識します(小さなCと大きなCに注意してください)。
そこで、ファイルの名前をCLIENT.c
プログラムに変更しました。
上記の答えは正しいです。例外処理で使用されます。 GCCバージョン6の manual には詳細があります(バージョン7のマニュアルにはありません)。エラーは、GCCに不明なJava例外をスローする外部関数をリンクするときに発生する可能性があります。