例外が発生するまでGDBでアプリケーションを実行する


102

私はマルチスレッドアプリケーションで作業しており、GDBを使用してそれをデバッグしたいと考えています。

問題は、私のスレッドの1つが次のメッセージで消え続けることです。

pure virtual method called
terminate called without an active exception
Abort

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

GDBでアプリを実行すると、スレッドが一時停止または再開されるたびに一時停止します。例外のあるスレッドの1つが停止するまでアプリを通常どおり実行し続けます。その時点ですべてが停止し、バックトレースを取得できます。


GDBが一時停止すると、どのような信号が報告されますか?あなたは次のようにコマンドを実行することができるはずhandle SIGUSR1 pass noprint nostop
Hasturkun

回答:


147

「キャッチポイント」(catch throw)を使用して、例外が生成された時点でデバッガーを停止することができます。

次のgdbマニュアルからの抜粋は、キャッチポイント機能について説明しています。


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

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

  • キャッチイベント

    イベントが発生したときに停止します。イベントは次のいずれかです。

    • スロー

      C ++例外のスロー。

    • キャッチ

      C ++例外のキャッチ。

    • エグゼクティブ

      execの呼び出し。現在、これはHP-UXでのみ使用できます。

    • フォーク

      フォークへの呼び出し。現在、これはHP-UXでのみ使用できます。

    • vfork

      vforkの呼び出し。現在、これはHP-UXでのみ使用できます。

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

      共有ライブラリの動的読み込み、またはライブラリlibnameの読み込み。現在、これはHP-UXでのみ使用できます。

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

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

  • tcatchイベント

    1つのストップでのみ有効なキャッチポイントを設定します。キャッチポイントは、イベントが初めてキャッチされた後に自動的に削除されます。

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

現在、GDBのC ++例外処理(キャッチスローとキャッチキャッチ)にはいくつかの制限があります。

  • 関数をインタラクティブに呼び出す場合、GDBは通常、関数の実行が終了すると制御を返します。ただし、呼び出しで例外が発生した場合、呼び出しは制御をユーザーに返すメカニズムをバイパスし、プログラムが異常終了するか、ブレークポイントに到達するか、GDBがリッスンしているシグナルをキャッチするか、終了するまでプログラムの実行を継続します。これは、例外のキャッチポイントを設定した場合でも当てはまります。インタラクティブな呼び出しでは、例外のキャッチポイントは無効になります。

  • インタラクティブに例外を発生させることはできません。

  • 例外ハンドラをインタラクティブにインストールすることはできません。

場合によっては、catchは例外処理をデバッグするための最良の方法ではありません。例外が発生した場所を正確に知る必要がある場合は、例外ハンドラが呼び出される前に停止することをお勧めします。代わりに例外ハンドラーにブレークポイントを設定した場合、例外が発生した場所を見つけるのは簡単ではない可能性があります。

例外ハンドラが呼び出される直前に停止するには、実装の知識が必要です。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の値に依存する条件付きブレークポイント(セクションブレーク条件を参照)を使用すると、特定の例外が発生したときにプログラムを停止できます。複数の条件付きブレークポイントを使用して、いくつかの例外のいずれかが発生したときにプログラムを停止できます。


キャッチする例外のタイプを指定することもできます(例:)catch throw std::runtime_exception
scai

5

__pure_virtualにブレークポイントを設定します


@JeffreyHillの回答では、現在__cxa_pure_virtualと呼ばれています。自分で確認する方法がわからないので、回答を編集したくありません。私は反対投票するつもりはありませんが、答えは今は間違っている可能性があり、何が正しいかを知っている誰かが編集する必要があります。
PhilippClaßen16年

5

FWIW、明らかにgcc 4.1では、適切な関数名が変更されており、この関数にブレークポイントを設定する必要があります。

__cxa_pure_virtual


0

以下の1つだけがgdb 8.3で私のために働きました:

break _Unwind_RaiseException

「catch throw」または「break __cxx_throw」は私には機能しませんでした。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.