Red Hat Training
A Red Hat training course is available for RHEL 8
3.2. GDB を使用したアプリケーションの内部状況の検証
アプリケーションが正しく機能しない理由を特定するには、実行を制御し、デバッガーで内部状態を検証します。本セクションでは、このタスクに GNU Debugger (GDB) を使用する方法を説明します。
3.2.1. GNU デバッガー (GDB)
Red Hat Enterprise Linux には GNU デバッガー (GDB) が含まれ、コマンドラインユーザーインターフェイスを使用して、プログラム内で何が起こっているかを調べることができます。
GDB 機能
1 つの GDB セッションで、以下のタイプのプログラムをデバッグできます。
- マルチスレッドプログラムおよびフォークプログラム
- 一度に複数のプログラム
-
TCP/IP ネットワーク接続経由で接続された
gdbserver
ユーティリティーを使用するリモートマシンまたはコンテナー内のプログラム
デバッグの要件
実行コードをデバッグするには、GDB では、その特定のコードのデバッグ情報が必要です。
- ユーザーが開発したプログラムでは、コードの構築中にデバッグ情報を作成できます。
- パッケージからインストールしたシステムプログラムの場合は、debuginfo パッケージをインストールする必要があります。
3.2.2. プロセスへの GDB の割り当て
プロセスを検証するには、GDB がプロセスに 割り当てられている 必要があります。
前提条件
GDB でのプログラムの起動
プログラムがプロセスとして実行していない場合は、GDB でプログラムを起動します。
$ gdb program
program は、ファイル名またはプログラムへのパスに置き換えます。
GDB は、プログラムの実行を開始するように設定します。run
コマンドでプロセスの実行を開始する前に、ブレークポイントと gdb
環境を設定できます。
実行中のプロセスに GDB を割り当て
プロセスとして実行中のプログラムに GDB を割り当てるには、以下を行います。
ps
コマンドで、プロセス ID (pid) を検索します。$ ps -C program -o pid h pid
program は、ファイル名またはプログラムへのパスに置き換えます。
このプロセスに GDB を割り当てます。
$ gdb -p pid
pid は、
ps
の出力にある実際のプロセス ID 番号に置き換えます。
実行中のプロセスに実行中の GDB を割り当てる
実行中のプロセスに実行中の GDB を割り当てるには、以下を行います。
GDB コマンド
shell
を使用してps
コマンドを実行し、プログラムのプロセス ID (pid) を検索します。(gdb) shell ps -C program -o pid h pid
program は、ファイル名またはプログラムへのパスに置き換えます。
attach
コマンドを使用して、GDB をプログラムに割り当てます。(gdb) attach pid
pid は、
ps
の出力にある実際のプロセス ID の番号に置き換えます。
場合によっては、GDB が適切な実行ファイルを検索できない可能性があります。file
コマンドを使用して、パスを指定します。
(gdb) file path/to/program
関連情報
- GDB を使用したデバッグ - 2.1 Invoking GDB
- GDB を使用したデバッグ - 4.7 Debugging an Already-running Process
3.2.3. GDB を使用したプログラムコードのステップ実行
GDB デバッガーがプログラムに割り当てられたら、複数のコマンドを使用して、プログラムの実行を制御できます。
前提条件
必要なデバッグ情報を利用できる状態にしている。
- プログラムはコンパイルされ、デバッグ情報で構築されている。
- 適切な debuginfo パッケージがインストールされている。
- GDB はデバッグするプログラムに割り当てられている。
コードをステップ実行する GDB コマンド
r
(run)-
プログラムの実行を開始します。引数を指定して
run
を実行すると、プログラムが通常起動したかのように、その引数が実行ファイルに渡されます。通常は、ブレークポイントの設定後にこのコマンドを実行します。 start
-
プログラムの実行を開始しますが、プログラムのメイン機能の開始時に停止します。
start
を引数と共に実行すると、その引数が、プログラムが通常起動したかのように実行ファイルに渡されます。
c
(continue)現在の状態からプログラムの実行を継続します。プログラムの実行は、以下のいずれかが True になるまで継続します。
- ブレークポイントに到達した場合
- 指定の条件を満たした場合
- プログラムによりシグナルを受信する場合
- エラーが発生した場合
- プログラムが終了する場合
n
(next)現在のソースファイルでコードが次の行に到達するまで、現在の状態からプログラムの実行を続行します。プログラムの実行は、以下のいずれかが True になるまで継続します。
- ブレークポイントに到達した場合
- 指定の条件を満たした場合
- プログラムによりシグナルを受信する場合
- エラーが発生した場合
- プログラムが終了する場合
s
(step)-
step
コマンドは、現在のソースファイル内のコードの連続行ごとに実行を停止することも行います。ただし、関数呼び出し を含むソース行で実行が現在停止すると、GDB は、関数呼び出しを入力した後 (実行後ではなく)、実行を停止します。 until
location- location オプションで指定したコードの場所に到達するまで、実行が継続されます。
fini
(finish)プログラムの実行を再開し、実行が関数から返されたときに停止します。プログラムの実行は、以下のいずれかが True になるまで継続します。
- ブレークポイントに到達した場合
- 指定の条件を満たした場合
- プログラムによりシグナルを受信する場合
- エラーが発生した場合
- プログラムが終了する場合
q
(quit)- 実行を終了し、GDB を終了します。
関連情報
- 「GDB ブレークポイントを使用して、定義したコードの場所で実行を停止」
- GDB を使用したデバッグ - 4.2 Starting your Program
- GDB を使用したデバッグ - 5.2 Continuing and Stepping
3.2.4. GDB でのプログラム内部値の表示
プログラムの内部変数の値を表示することは、プログラムの実行内容を理解する際に重要です。GDB は、内部変数の検査に使用できる複数のコマンドを提供します。これらのコマンドの中で最も有用なものは次のとおりです。
p
(print)指定された引数の値を表示します。通常、引数は単純な 1 つの値から構造まで、あらゆる複雑な変数の名前です。引数には、プログラム変数やライブラリー関数の使用、テストするプログラムに定義する関数など、現在の言語で有効な式も指定できます。
pretty-printer Python スクリプトまたは Guile スクリプトを使用して GDB を拡張し、
print
コマンドを使用して、(クラス、構造などの) データ構造をカスタマイズ表示することができます。bt
(backtrace)現在の実行ポイントに到達するために使用される関数呼び出しのチェーン、または実行が終了するまで使用される関数のチェーンを表示します。これは、深刻なバグ (セグメント障害など) を調査し、見つけるのが困難な原因に役に立ちます。
backtrace
コマンドにfull
オプションを追加すると、ローカル変数も表示されます。bt
コマンドおよびinfo frame
コマンドを使用して表示されるデータをカスタマイズして表示するために、frame filter Python スクリプトで GDB を拡張できます。フレーム という用語は、1 つの関数呼び出しに関連付けられたデータを指します。info
info
コマンドは、さまざまな項目に関する情報を提供する汎用コマンドです。これは、説明する項目を指定するオプションを取ります。-
info args
コマンドは、現在選択されているフレームの関数呼び出しのオプションを表示します。 -
info locals
コマンドは、現在選択されているフレームにローカル変数を表示します。
使用できる項目をリスト表示するには、GDB セッションで
help info
コマンドを実行します。(gdb) help info
-
l
(list)-
プログラムが停止するソースコードの行を表示します。このコマンドは、プログラムの実行が停止した場合のみ利用できます。
list
は、厳密には内部状態を表示するコマンドではありませんが、ユーザーがプログラムの実行の次の手順で内部状態にどのような変更が発生するかを理解するのに役立ちます。
関連情報
- Red Hat Developers Blog エントリー - The GDB Python API
- GDB でのデバッグ: Pretty Printing
3.2.5. GDB ブレークポイントを使用して、定義したコードの場所で実行を停止
多くの場合、コードの一部のみが検証されます。ブレークポイントは、コード内の特定の場所でプログラムの実行を停止するように GDB に指示を出すマーカーです。ブレークポイントは、ソースコードの行に関連付けられているのが最も一般的です。その場合、ブレークポイントを配置するには、ソースファイルと行番号を指定する必要があります。
ブレークポイントを配置する には、以下を行います。
ソースコード ファイル の名前と、そのファイルの 行 を指定します。
(gdb) br file:line
ファイル が存在しない場合は、現在の実行ポイントにソースファイルの名前が使用されます。
(gdb) br line
または、関数名を使用して、起動時にブレークポイントを配置します。
(gdb) br function_name
タスクを特定の回数反復すると、プログラムでエラーが発生する可能性があります。実行を停止するために追加の 条件 を指定するには、以下を実行します。
(gdb) br file:line if condition
condition を、C または C++ 言語の条件に置き換えます。file と line は、上記と同様に、ファイル名および行数に置き換えます。
全ブレークポイントおよびウォッチポイントの状態を 検査 する場合は、以下のコマンドを実行します。
(gdb) info br
info br
の出力で表示された 番号 を使用してブレークポイントを 削除 するには、以下のコマンドを実行します。(gdb) delete number
指定の場所のブレークポイントを 削除 するには、次のコマンドを実行します。
(gdb) clear file:line
関連情報
- GDB を使用したデバッグ - 5.1 Breakpoints, Watchpoints, and Catchpoints
3.2.6. データへのアクセスや変更を停止するための GDB ウォッチポイントの使用
多くの場合、特定のデータが変更されたり、アクセスされるまでプログラムを実行させることには利点があります。次の例は、最も一般的な使用例です。
前提条件
- GDB の理解
GDB でのウォッチポイントの使用
ウォッチポイントは、プログラムの実行を停止するように GDB に指示を出すマーカーです。ウォッチポイントはデータに関連付けられています。ウォッチポイントを配置するには、変数、複数の変数、またはメモリーアドレスを記述する式を指定する必要があります。
データの 変更 (書き込み) を行うために、ウォッチポイントを 配置 するには、次を使用します。
(gdb) watch expression
expression を、監視する内容を記述する式に置き換えます。変数の場合、式 は、変数の名前と同じです。
データ アクセス (読み込み) のためのウォッチポイントを 配置 するには、以下を実行します。
(gdb) rwatch expression
任意の データへのアクセス (読み取りおよび書き込みの両方) のためにウォッチポイントを 配置 するには、以下を実行します。
(gdb) awatch expression
全ウォッチポイントおよびブレークポイントの状態を 検査 するには以下を実行します。
(gdb) info br
ウォッチポイントを 削除 するには、以下を実行します。
(gdb) delete num
num オプションを、
info br
コマンドで返された番号に置き換えます。
関連情報
- GDB を使用したデバッグ - Setting Watchpoints
3.2.7. GDB でのフォークまたはスレッド化されたプログラムのデバッグ
プログラムによっては、フォークまたはスレッドを使用して、並行コード実行を実現します。複数の同時実行パスをデバッグするには、特別な留意点があります。
前提条件
- プロセスのフォークおよびスレッドの概念を理解している。
GDB でのフォークされたプログラムのデバッグ
フォークとは、プログラム (親) が独立したコピー (子) を作成する状況です。フォーク発生時の GDB の動作に影響を与えるには、以下の設定およびコマンドを使用します。
follow-fork-mode
設定で、フォークの後に GDB が親または子に従うかどうかを制御します。set follow-fork-mode parent
- フォークの後に、親プロセスのデバッグを実行します。これがデフォルトになります。
set follow-fork-mode child
- フォークの後に子のプロセスをデバッグします。
show follow-fork-mode
-
follow-fork-mode
の現在の設定を表示します。
set detach-on-fork
設定では、GDB が (続いていない) 他のプロセスを制御するか、そのまま実行させるかを制御します。set detach-on-fork on
-
続いていないプロセス (
follow-fork-mode
の値により異なる) は切り離され、独立して実行されます。これがデフォルトになります。 set detach-on-fork off
-
GDB は両方のプロセスの制御を維持します。フォローしているプロセス (
follow-fork-mode
の値による) は通常通りにデバッグされ、他は一時停止されます。 show detach-on-fork
-
detach-on-fork
の現在の設定を表示します。
GDB でのスレッド化されたプログラムのデバッグ
GDB には、個別のスレッドをデバッグして、独立して操作し、検査する機能があります。GDB が検査したスレッドのみを停止させるには、set non-stop on
コマンドおよび set target-async on
コマンドを使用します。これらのコマンドは、.gdbinit
ファイルに追加できます。その機能が有効になると、GDB がスレッドのデバッグを実行する準備が整います。
GDB は、現在のスレッド の概念を使用します。デフォルトでは、コマンドは現在のスレッドのみに適用されます。
info threads
-
現在のスレッドを示す
id
番号およびgid
番号を使用してスレッドのリストを表示します。 thread id
-
指定した
id
を現在のスレッドとして設定します。 thread apply ids command
-
command
コマンドを、ids
でリスト表示されたすべてのスレッドに適用します。ids
オプションは、スペースで区切られたスレッド ID のリストです。特殊な値all
は、すべてのスレッドにコマンドを適用します。 break location thread id if condition
-
スレッド番号
id
に対してのみ特定のcondition
を持つ特定のlocation
にブレークポイントを設定します。 watch expression thread id
-
スレッド番号
id
に対してのみexpression
で定義されるウォッチポイントを設定します。 command&
-
command
コマンドを実行して、すぐに gdb プロンプト(gdb)
に戻りますが、バックグラウンドでコード実行が続行されます。 interrupt
- バックグラウンドでの実行が停止されます。
関連情報
- GDB を使用したデバッグ - 4.10 Debugging Programs with Multiple Threads
- GDB を使用したデバッグ: 4.11 Debugging Forks