web-dev-qa-db-ja.com

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

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

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

pure virtual method called
terminate called without an active exception
Abort

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

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

96
Ankur Sethi

「キャッチポイント」(catch throw)例外が生成されるポイントでデバッガーを停止します。

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


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

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

  • catchevent

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

    • スロー

      C++例外のスロー。

    • キャッチ

      C++例外のキャッチ。

    • 幹部

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

    • fork

      フォークの呼び出し。これは現在、HP-UXでのみ利用可能です。

    • vfork

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

    • loadorload libname

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

    • アンロードorlibnameのアンロード

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

  • tcatchイベント

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

使用 info breakコマンドは、現在のキャッチポイントをリストします。

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

* If you call a function interactively, GDB normally returns control to you when the function has finished executing. If the call raises an exception, however, the call may bypass the mechanism that returns control to you and cause your program either to abort or to simply continue running until it hits a breakpoint, catches a signal that GDB is listening for, or exits. This is the case even if you set a catchpoint for the exception; catchpoints on exceptions are disabled within interactive calls.

* You cannot raise an exception interactively.

* You cannot install an exception handler interactively. 

キャッチは例外処理をデバッグするための最良の方法ではない場合があります。例外が発生した場所を正確に知る必要がある場合、アンワインドが発生する前にスタックを確認できるため、例外ハンドラーが呼び出される前に停止する方が良いです。代わりに例外ハンドラーにブレークポイントを設定すると、例外が発生した場所を見つけるのが容易ではない場合があります。

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

140
Dan

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

5
Steve Folly

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

__cxa_pure_virtual

4
Jeffrey Hill