110

これはOS開発サイトからの中古の質問ですが、どこにもまともな説明が見つからなかったので興味津々でした。

gccを使用して自立型C++プログラムをコンパイルおよびリンクすると、次のようなリンカーエラーが発生することがあります。

out/kernel.o:(.eh_frame+0x11): undefined reference to `__gxx_personality_v0'

これは明らかに、このシンボルがlibstdc ++で定義されているためです。これは、独立した環境では欠落しています。問題を修正するには、このシンボルをどこかに定義する必要があります。

void *__gxx_personality_v0;

どちらがいいのですが、魔法のように機能するものは好きではありません...それで、問題は、このシンボルの目的は何ですか?

4

6 に答える 6

99

たとえば、別の質問に対する私の回答のアセンブリ出力で確認できます。その回答で述べたように、その使用はItanium C++ ABIによって定義され、 Personality Routineと呼ばれます。

グローバル NULL void ポインターとして定義することで「機能する」理由は、おそらく何も例外をスローしていないためです。何かが例外をスローしようとすると、それが正しく動作しないことがわかります。

もちろん、何も例外を使用していない場合は、それらを無効にすることができます-fno-exceptions(RTTI を使用していない場合は、追加することもできます-fno-rtti)。それらを使用している場合は、(他の回答がすでに述べたように)g++代わりに とリンクする必要があります。gccこれにより、追加-lstdc++されます。

于 2008-11-30T19:00:53.107 に答える
12

例外処理は、独立した実装に含まれています。

gccこれは、コードのコンパイルに を使用する可能性があるためです。このオプションを指定してコンパイルすると、リンカー プロセスを呼び出すときに-###linker-option が欠落していることに気付くでしょう。-lstdc++でコンパイルするg++と、そのライブラリが含まれるため、そのライブラリで定義されたシンボルが含まれます。

于 2008-11-30T18:28:38.380 に答える
12

これは例外処理の一部です。gcc EH メカニズムでは、さまざまな EH モデルを混在させることができ、パーソナリティ ルーチンが呼び出されて、例外が一致するかどうか、どのファイナライズを呼び出すかなどを決定します。この特定のパーソナリティ ルーチンは、C++ 例外処理用です (たとえば、gcj/Java例外処理)。

于 2008-11-30T17:27:27.427 に答える
6

このエラーが一度発生し、原因がわかりました:

gcc コンパイラを使用してCLIENT.Cいて、C++ プログラムではなく C プログラムを実行しているにもかかわらず、ファイルが呼び出されました。

gcc は.C拡張子を C++ プログラムとして、拡張子を C プログラムとして認識し.cます (小さな c と大きな C に注意してください)。

そのため、ファイルCLIENT.cプログラムの名前を変更したところ、機能しました。

于 2014-07-16T07:36:57.003 に答える
6

libstd++コード ベースの簡単な grep により、次の 2 つの使用法が明らかになりました__gx_personality_v0

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 にジャンプし、segfault が発生します。

于 2008-11-30T17:35:59.033 に答える