21

この質問は何度も聞かれていますが、問題の解決策が見つかりません。

次のような状況があります。

   A
  / \
 /   \
B <-- C
  • A はクラスを含む共有ライブラリですEException
  • B と C は A に対してリンクします
  • Cも共有ライブラリです
  • B は実行時に C を動的に読み込みます

ある時点で、C は次のインスタンスをスローしますEException

void doSometing() {
    throw EException("test-message");
}

私はこの例外をキャッチしBたいと思います:

try {
    doSomething();
} catch (const EException& ex) {
    // Not reached
} catch (...) {
    // Not reached
}

ただし、コードで述べたように、どちらの catch 句も呼び出されません。代わりに、このコードが実行されるスレッドが中止されます。

私は次のことを試しました:

  • の可視性属性は、EExceptionA のコンパイル時に「デフォルト」に設定されます。
  • EExceptionヘッダー ファイルには宣言のみが含まれます
  • -fvisibility=hiddenA、B、C でリンカー オプションを使用しています
  • -ECでリンカー オプションを使用しています

nmI get for の使用A:

0000000000066260 T EException::EException(QString const&)
0000000000066306 T EException::EException(EException const&)
00000000000661d0 T EException::EException() 
0000000000066260 T EException::EException(QString const&) 
0000000000066306 T EException::EException(EException const&) 
00000000000661d0 T EException::EException() 
00000000000664de T EException::~EException()
000000000006641e T EException::~EException() 
000000000006641e T EException::~EException() 
00000000000663b6 T EException::operator=(EException const&)
<...>
000000000028de40 V typeinfo for EException
000000000028dd80 V typeinfo for EException*
000000000007342b V typeinfo name for EException
0000000000072ab7 V typeinfo name for EException*
000000000028de00 V vtable for EException

の場合B:

U EException::EException(QString const&)
U EException::~EException()
<...>
0000000000726f60 V typeinfo for EException

およびC:

U EException::EException(QString const&)
U EException::~EException()
<...>
U typeinfo for EException

が提供するものを使用しているときに、Bの独自の typeinfo を使用するという問題はありますか? どうすればこれを修正できますか?EExceptionCA

私の環境:

  • x86_64-linux-gnu 上の gcc 4.6.3
  • Qtを使用して

ご協力ありがとうございました!

4

5 に答える 5

3

共有ライブラリの境界を越えて RTTI シンボルを使用する gcc < 4.5 でも同様の問題がありましたが、gcc 4.6 ではそうではありませんでした。ただし、次の情報が役立つ場合があります。

すでに述べたように、vtable (typeinfo オブジェクトへのエントリを含む)EExceptionは一部の翻訳単位で重複しているように見えますが、これは明らかに gcc < 4.5 の問題でした (まあ、これは libsupc++ の問題であり、私が知る限り、そうではありません)。 type_info オブジェクトをマージします)。EException仮想の行外デストラクタ (ヘッダーの最初の仮想関数宣言である必要があります) を定義して vtable を固定すると、Aうまくいきました。

の完全なヘッダー ファイルを投稿するEExceptionことも役立つ場合があります。

于 2012-06-09T16:01:04.497 に答える
1

私見、これはコンパイラフラグとは何の関係もありません。

例外オブジェクトをexternとして宣言し、メインバイナリ以外の場所に実装を提供しないでください。

これにより、リンカ(ダイナミックリンカBTW)は可能な唯一の実装を使用するようになります。

extern定義でのみtypeinfoは生成されません。

于 2012-08-01T09:55:23.590 に答える
1

チェック

-fvisibility=非表示

リンカー設定のオプション。設定されている場合は、に変更します

-fvisibility=デフォルト

于 2012-07-14T09:31:09.630 に答える
0

B は独自の EException クラス定義を使用していV typeinfo for EExceptionますが、C は未解決のものを使用しているようです (U は、型が現在の翻訳単位で未定義であり、ローダーと動的リンカーによって解決される必要があることを意味します)。

B がまだ共有ライブラリであり、A と静的にリンクされているのではなく、動的にリンクされていることを確認してください。これにより、C が A のものを見つけられなくなります。B が A と同じタイプをリンクしないことがわかりません。ヘッダーに注意してください ^^。

于 2012-05-29T01:57:00.573 に答える
0

AをコンパイルしBてみてくださいC(-rdynamicリンケージ段階で)

GCC のマニュアル ページでは、-rdynamic について説明しています。

フラグ -export-dynamic を、それをサポートするターゲットで ELF リンカに渡します。これにより、リンカーは、使用されているシンボルだけでなく、すべてのシンボルを動的シンボル テーブルに追加するように指示されます。このオプションは、" dlopen " を使用する場合や、プログラム内からバックトレースを取得できるようにする場合に必要です。

于 2012-06-15T18:19:20.857 に答える