1. ホーム
  2. c++

[解決済み] GDBで例外が発生するまでアプリケーションを実行する

2022-10-17 21:08:40

質問

マルチスレッドアプリケーションを開発中で、GDB を使用してデバッグしたいのですが。

問題は、私のスレッドの1つがメッセージとともに死に続けていることです。

pure virtual method called
terminate called without an active exception
Abort

私はそのメッセージの原因を知っていますが、私のスレッドのどこでそれが発生するのかわかりません。バックトレースがあると本当に助かります。

GDB で私のアプリを実行すると、スレッドが中断または再開されるたびに一時停止します。私のアプリは、スレッドの 1 つがその例外で死ぬまで正常に実行し続けたいのですが、その時点ですべてが停止し、バックトレースを取得することができます。

どのように解決するのですか?

キャッチポイント(quot;catchpoint")を使ってみるとよいでしょう。 catch throw ) を使用して、例外が生成された時点でデバッガを停止することができます。

以下のような の抜粋 gdbマニュアルから、キャッチポイント機能についての説明です。


5.1.3 キャッチポイントの設定

C++例外や共有ライブラリの読み込みなど、特定の種類のプログラムイベントに対してデバッガを停止させるために、キャッチポイントを使用することができます。キャッチポイントを設定するには、catchコマンドを使用します。

  • catch イベント

    停止するタイミング イベント が発生したとき。eventには以下のいずれかを指定することができる。

    • 投げる

      C++の例外を投げること。

    • キャッチ

      C++の例外をキャッチすることです。

    • エグゼクティブ

      execの呼び出し。これは現在HP-UXでのみ利用可能です。

    • フォーク

      fork の呼び出し。これは現在HP-UXでのみ利用可能です。

    • vfork

      vfork の呼び出しです。これは現在 HP-UX でのみ利用可能です。

    • ロード または libname をロードする

      任意の共有ライブラリの動的ロード、またはライブラリ libname のロードを行います。これは現在 HP-UX でのみ利用可能です。

    • アンロード または libname のアンロード

      動的にロードされた共有ライブラリのアンロード、または、ライブラリ libname のアンロードを行います。これは現在 HP-UX でのみ利用可能です。

  • tcatchイベント

    1回の停止に対してのみ有効なキャッチポイントを設定します。このキャッチポイントは、最初にイベントをキャッチした後、自動的に削除されます。

を使用します。 info break コマンドを使用して、現在のキャッチポイントを一覧表示します。

現在、GDBでのC++例外処理(catch throwとcatch catch)にはいくつかの制限があります。

  • 関数を対話的に呼び出す場合、GDBは通常、関数の実行が終了した時点で制御をあなたに返します。しかし、呼び出しが例外を発生させた場合、制御を戻す機構をバイパスし、プログラムを中断させるか、ブレークポイントに到達するか、GDB が待ち受けている信号をキャッチするか、終了するまで単に実行を継続させるかもしれない。これは、例外のキャッチポイントを設定した場合でも同様です。例外のキャッチポイントは、インタラクティブな呼び出しの中では無効です。

  • 対話的に例外を発生させることはできません。

  • 例外ハンドラを対話的にインストールすることはできません。

例外がどこで発生したかを正確に知る必要がある場合、例外ハンドラが呼び出される前に停止する方がよいでしょう。例外ハンドラでブレークポイントを設定すると、例外が発生した場所を見つけるのは簡単ではないかもしれません。

例外ハンドラが呼び出される直前で停止するには、実装に関するいくつかの知識が必要です。GNU C++の場合、例外は以下のANSI Cインタフェースを持つ__raise_exceptionというライブラリ関数を呼び出すことで発生します。

/* addr is where the exception identifier is stored.
   id is the exception identifier.  */
void __raise_exception (void **addr, void *id);

スタックの巻き戻しが行われる前にデバッガが全ての例外をキャッチするようにするには、 __raise_exception にブレークポイントを設定します (ブレークポイント、ウォッチポイント、および例外を参照)。

id の値に依存する条件付きブレークポイント (ブレーク条件参照) を使用すると、特定の例外が発生したときにプログラムを停止させることができます。複数の条件付きブレークポイントを使用すると、多くの例外のいずれかが発生したときにプログラムを停止させることができます。