gdb によるデバッグ

GNU デバッガー (gdb) を使用すると、別のプログラムの実行中にそのプログラムの内部を調べたり、クラッシュの瞬間にプログラムが実行していた内容を後から確認したりできます。

gdb ではコードの実行を検査および制御することができ、クラッシュまたは一般的な誤動作の原因を診断する際に便利です。 gdb は Java™ プロセスを処理しないため、純粋な Java プログラムでは使用が制限されます。 これは、ネイティブ・ライブラリーとJVM自体のデバッグに役立ちます。

gdb の実行

gdb は、以下の 3 とおりの方法で実行できます。

プログラムの開始
通常は、コマンド gdb <application> を使用して、gdb の制御下でプログラムが開始されます。 ただし、Java の起動方法が原因で、環境変数を設定してから Java を呼び出すことにより、 gdb を開始する必要があります。
export IBM_JVM_DEBUG_PROG=gdb
java
次に、 gdb プロンプトを受け取り、実行コマンドと Java 引数を指定します。
r <java_arguments>
実行中のプログラムへの接続
Java プログラムが既に実行されている場合は、 gdbの下で制御できます。 実行中のプログラムのプロセス ID が必要です。次に、最初の引数として Java アプリケーションを使用し、2 番目の引数としてプロセス ID を使用して、 gdb が開始されます。
gdb <Java Executable> <PID>

実行中のプログラムに gdb が接続されると、このプログラムは一時停止状態になり、そのコード内での位置がビューアーに表示されます。 その後、プログラムは gdb の制御下に入り、ユーザーは、コマンドを実行して変数を設定および表示したり、コードの実行を広く制御したりする作業を開始できるようになります。

システム・ダンプ (コア・ファイル) に対する実行
通常、システム・ダンプはプログラムがクラッシュした際に生成されます。 このシステム・ダンプに対して、gdb を実行することができます。 システム・ダンプには、クラッシュ発生時におけるプログラムの状態が含まれています。 クラッシュの原因となったすべての変数およびレジスターの値を、gdb を使用して調べます。 この情報は、クラッシュの原因を突き止める上で役に立ちます。 システム・ダンプをデバッグするには、最初の引数として Java アプリケーション・ファイルを、2 番目の引数としてシステム・ダンプ名を指定して、 gdb を開始します。
gdb <Java Executable> <system dump>

システム・ダンプに対して gdb を実行すると、最初に、プログラムが受け取った終了シグナル、その時点で実行されていた関数、さらには、障害を発生させたコード行などの情報が表示されます。

プログラムが gdbの制御下に入ると、ウェルカム・メッセージが表示され、その後にプロンプト (gdb) が表示されます。 プログラムは現在、ユーザーが命令を入力するのを待っています。 指示ごとに、プログラムはユーザーが選択した方法で処理を続行します。

ブレークポイントおよび監視ポイントの設定

以下のコマンドを使用して、特定の行または関数に関してブレークポイントを設定できます。

break linenumber

または

break functionName

ブレークポイントの設定後に continue コマンドを使用すると、プログラムがブレークポイントに達するまで実行されます。

指定の条件に達した場合にのみプログラムを一時停止するように、条件を使用したブレークポイントを設定します。 例えば、 breakpoint 39 if var == value を使用すると、プログラムは行 39 に達すると停止しますが、これは変数が指定された値と等しい場合に限られます。

変数が「いつ」、「どこで」特定の値になったのかを知る必要がある場合には、監視ポイントを使用します。 監視ポイントは、問題の変数がスコープ内にあるときに設定します。 設定後は、この変数が指定値に達するたびにアラートが出されます。 このコマンドの構文は、watch var == value です。

どのブレークポイントおよび監視ポイントが設定されているかを確認するには、info コマンドを使用します。

info break
info watch
gdb は、ブレークポイントまたは監視ポイントに達すると、次に実行するように設定されているコード行を表示します。 8行目にブレークポイントを設定すると、7行目の実行が完了した後、8行目の実行前にプログラムが止まります。 ブレークポイントとウォッチポイントだけでなく、プログラムは特定のシステム信号を受信すると止まります。 以下のコマンドを使用すると、これらのシステム・シグナルを受け取るたびにデバッグ・ツールが一時停止しないようにすることができます。
handle sig32 pass nostop noprint 
handle sigusr2 pass nostop noprint 

コードの検査

コードの該当する位置に到達したときにコードを検査する方法はいくつかあります。 最も便利なのはbacktrace (省略形は bt) で、これは呼び出しスタックを示します。 呼び出しスタックは関数フレームの集合で、各関数フレームには関数パラメーターやローカル変数などの情報が含まれています。 これらの関数フレームは、実行された順に呼び出しスタックに積まれていきます。 つまり、最後に呼び出された関数が、呼び出しスタックの最上部に表示されます。 呼び出しスタックを調べることで、プログラムの実行証跡を追跡することができます。 呼び出しスタックでは、行の先頭にフレーム番号が表示され、その後に、呼び出し側関数のアドレス、関数名、および関数のソース・ファイルと続きます。 例:
#6 0x804c4d8 in myFunction () at myApplication.c

ファンクションフレームの詳細情報を表示するには、フレーム番号を指定するパラメータとともにframeコマンドを使います。 フレームを選択した後、コマンドprint varでその変数を表示できます。

printコマンドで変数値を変更します (例: print var = newValue)。

info localsコマンドは、選択関数のすべてのローカル変数値を表示します。

プログラムの正確な実行順序に従うには、stepnextコマンドを使ってください。 どちらのコマンドにも、実行する行数を指定するオプション・パラメーターがあります。 ただし、nextは関数呼び出しは1行の実行として扱われ、呼び出された関数の各行は一度に step 1段取りずつ進行します。

有用なコマンド

コードのデバッグが終了すると、 runコマンドによってプログラムが最後またはクラッシュポイントまで実行されます。 gdbを終了するには、 quit コマンドを使用します。

その他の便利なコマンドは以下のとおりです。

ptype
変数のデータ型を表示します。
info share
現在ロードされている共有ライブラリーの名前を表示します。
info functions
すべての関数プロトタイプを表示します。
list
ソース・コードの現在行の前後 10 行を表示します。
help
トピックのリストが表示されます。各トピックには、そのトピックに関する詳細なヘルプを表示するために呼び出すことができる、ヘルプ・コマンドがある場合があります。