[Contents]   [Back]   [Prev]   [Up]   [Next]   [Forward]  


停止と継続

デバッガを使用する主な目的は、 プログラムが終了してしまう前に停止させたり、 問題のあるプログラムを調査して何が悪いのかを調べたりすることにあります。

GDB内部においてプログラムが停止する原因はいくつかあります。 例えば、 シグナルの受信、 ブレイクポイントへの到達、 stepコマンドのようなGDBコマンドの実行後の新しい行への到達などです。 プログラムが停止すると、 変数の値の調査や設定、 新しいブレイクポイントの設定、 既存のブレイクポイントの削除などを行った後に、 プログラムの実行を継続することができます。 通常、 GDBが表示するメッセージは、 ユーザ・プログラムの状態について多くの情報を提供してくれます。 ユーザはいつでも明示的にこれらの情報を要求することができます。

info program
ユーザ・プログラムの状態に関する情報を表示します。 表示される情報は、 そのプログラムの実行状態 (実行中か否か)、 そのプログラムのプロセス、 プログラムが停止した理由です。

ブレイクポイント、ウォッチポイント、キャッチポイント

ブレイクポイントによって、 プログラム内のある特定の箇所に到達するたびに、 プログラムを停止することができます。 個々のブレイクポイントについて、 そのブレイクポイントにおいてプログラムを停止させるためには満足されなければならない、 より詳細な条件を設定することができます。 ブレイクポイントの設定は、 いくつかあるbreakコマンドのいずれかによって行います (ブレイクポイントの設定参照)。 行番号、 関数名、 プログラム内における正確なアドレスを指定することで、 プログラムのどこで停止するかを指定することができます。

HP-UX、 SunOS 4.x、 SVR4、 Alpha OSF/1上では、 実行開始前に共用ライブラリ内にブレイクポイントを設定することもできます。 HP-UXシステムでは、 ちょっとした制約があります。 プログラムによって直接呼び出されるのではない共用ライブラリ・ルーチン (例えば、 pthread_createの呼び出しにおいて、 引数として指定されるルーチン) にブレイクポイントをセットするためには、 そのプログラムの実行が開始されるまで待たなければなりません。

ウォッチポイントは、 ある式の値が変化したときにユーザ・プログラムを停止させる、 特別なブレイクポイントです。 ウォッチポイントは、 他のブレイクポイントと同じように管理することができますが、 設定だけは特別なコマンドで行います (ウォッチポイントの設定参照)。 有効化、 無効化、 および削除を行うときに使用する各コマンドは、 対象がブレイクポイントであってもウォッチポイントであっても同一です。

ブレイクポイントでGDBが停止するたびに、 常に自動的にユーザ・プログラム内のある値を表示させるようにすることができます。 自動表示 を参照してください。

キャッチポイントは、 C++の例外の発生やライブラリのローディングのようなある種のイベントが発生したときに、 ユーザ・プログラムを停止させる、 また別の特殊なブレイクポイントです。 ウォッチポイントと同様、 キャッチポイントを設定するために使用する特別なコマンドがあります。 (キャッチポイントの設定参照)。 しかし、 この点を除けば、 キャッチポイントを他のブレイクポイントと同様に管理することができます。 (ユーザ・プログラムがシグナルを受信したときに停止するようにするためには、 handleコマンドを使用します。 シグナル を参照してください)。

ユーザが新規に作成した個々のブレイクポイント、 ウォッチポイント、 キャッチポイントに対して、 GDBは番号を割り当てます。 この番号は1から始まる連続する整数値です。 ブレイクポイントのさまざまな側面を制御するコマンドの多くにおいて、 変更を加えたいブレイクポイントを指定するのにこの番号を使用します。 個々のブレイクポイントを有効化無効化することができます。 無効化されたブレイクポイントは、 再度有効化されるまで、 ユーザ・プログラムの実行に影響を与えません。

いくつかのGDBコマンドでは、 操作対象となるブレイクポイントの範囲を指定することができます。 ブレイクポイントの範囲とは、 `5'のような単一のブレイクポイント番号、 または、 `5-7'のように、 昇順に並んだ2つのブレイクポイント番号をハイフンで区切ったもののいずれかです。 あるコマンドに対してブレイクポイントの範囲が指定された場合、 その範囲にあるすべてのブレイクポイントが操作の対象となります。

ブレイクポイントの設定

ブレイクポイントは、 breakコマンド (省略形はb) によって設定されます。 デバッガのコンビニエンス変数`$bpnum'に、 最後に設定されたブレイクポイントの番号が記録されます。 コンビニエンス変数の用途については、 コンビニエンス変数 を参照してください。

ブレイクポイントの設定箇所を指定する方法はいくつかあります。

break function
関数functionのエントリにブレイクポイントを設定します。 ソース言語が (例えばC++のように) シンボルのオーバーロード機能を持つ場合、 functionは、 プログラムを停止させる可能性を持つ1つ以上の箇所を指すことがあります。 このような状況に関する説明については、 ブレイクポイント・メニュー を参照してください。
break +offset
break -offset
その時点において選択されているスタック・フレームにおいて実行が停止している箇所から、 指定された行数だけ先または手前にブレイクポイントを設定します。 スタック・フレームについては、 スタック・フレーム を参照してください。
break linenum
カレントなソース・ファイル内のlinenumで指定される行番号を持つ行に、 ブレイクポイントを設定します。 ここで「カレントなソース・ファイル」とは、 最後にソース・コードが表示されたファイルを指します。 このブレイクポイントは、 その行に対応するコードが実行される直前に、 ユーザ・プログラムを停止させます。
break filename:linenum
filenameで指定されるソース・ファイルのlinenumで指定される番号の行に、 ブレイクポイントを設定します。
break filename:function
filenameで指定されるソース・ファイル内のfunctionで指定される関数エントリにブレイクポイントを設定します。 同じ名前の関数が複数のファイルに存在する場合以外は、 ファイル名と関数名を同時に指定する必要はありません。
break *address
addressで指定されるアドレスにブレイクポイントを設定します。 これは、 プログラムの中の、 デバッグ情報やソース・ファイルが手に入らない部分にブレイクポイントを設定するのに使用できます。
break
引数なしで実行されると、 breakコマンドは、 選択されたスタック・フレーム内において次に実行される命令にブレイクポイントを設定します (スタックの検査参照)。 最下位にあるスタック・フレーム以外のフレームが選択されていると、 このブレイクポイントは、 制御がそのフレームに戻ってきた時点でユーザ・プログラムを停止させます。 これが持つ効果は、 選択されたフレームの下位にあるフレームにおいて finishコマンドを実行するのと似ています。 ただし、 1つ異なるのは、 finishコマンドがアクティブなブレイクポイントを残さないという点です。 最下位のスタック・フレームにおいて引数なしで breakコマンドを実行した場合、 GDBは、 そのときに停止していた箇所に次に到達したときにユーザ・プログラムを停止させます。 これは、 ループの内部では便利でしょう。 GDBは通常、 実行を再開したときに、 最低でも1命令が実行されるまでの間はブレイクポイントの存在を無視します。 そうでなければ、 ブレイクポイントで停止した後、 そのブレイクポイントを無効にしない限り先へ進めないことになってしまいます。 この規則は、 ユーザ・プログラムが停止したときに既にそのブレイクポイントが存在したか否かにかかわらず、 適用されます。
break ... if cond
condで指定される条件式付きでブレイクポイントを設定します。 このブレイクポイントに達すると、 必ず条件式condが評価されます。 その結果がゼロでない場合、 すなわち、 condの評価結果が真である場合のみ、 ユーザ・プログラムを停止します。 `...'の部分には、 これまでに説明してきた、 停止箇所を指定するための引数のいずれかが入ります (`...'は省略も可能です)。 ブレイクポイントの条件式の詳細については、 ブレイクポイントの成立条件 を参照してください。
tbreak args
プログラムを1回だけ停止させるブレイクポイントを設定します。 argsの部分はbreakコマンドと同様であり、 ブレイクポイントも同じように設定されますが、 tbreakにより設定されたブレイクポイントは、 プログラムが最初にそこで停止した後に自動的に削除されます。 ブレイクポイントの無効化 を参照してください。
hbreak args
ハードウェアの持つ機能を利用したブレイクポイントを設定します。 argsの部分はbreakコマンドと同様であり、 ブレイクポイントも同じように設定されますが、 hbreakにより設定されるブレイクポイントは、 ハードウェアによるサポートを必要とします。 ターゲット・ハードウェアによっては、 このような機能を持たないものもあるでしょう。 これの主な目的は、 EPROM/ROMコードのデバッグであり、 ある命令を変更することなく、 その命令にブレイクポイントを設定することです。 これは、 SPARClite DSUといくつかのx86ベースのターゲットが提供する、 新しいトラップ発生機能と組み合わせて使用することができます。 デバッグ・レジスタに割り当てられた データ・アドレスや命令アドレスをプログラムがアクセスすると、 これらのターゲットはトラップを発生させます。 ただし、 ハードウェアの提供するブレイクポイント・レジスタが取ることのできるブレイクポイントの数には限りがあります。 例えば、 DSUではデータ・ブレイクポイントを同時には2つまでしか取れないので、 3つ以上使用しようとすると、 GDBはそれを拒絶します。 このような場合、 不要になったハードウェア・ブレイクポイントを削除または無効化 (ブレイクポイントの無効化参照) してから、 新しいハードウェア・ブレイクポイントを設定してください 。 ブレイクポイントの成立条件 を参照してください。
thbreak args
ハードウェアの機能を利用して、 プログラムを1回だけ停止させるブレイクポイントを設定します。 argsの部分はhbreakコマンドと同様であり、 ブレイクポイントも同じように設定されます。 しかし、 tbreakコマンドの場合と同様、 最初にプログラムがそこで停止した後に、 このブレイクポイントは自動的に削除されます。 また、 hbreakコマンドの場合と同様、 このブレイクポイントはハードウェアによるサポートを必要とするものであり、 ターゲット・ハードウェアによっては、 そのような機能がないこともあるでしょう。 ブレイクポイントの無効化 を参照してください。 また、 ブレイクポイントの成立条件 もあわせて参照してください。。
rbreak regex
regexで指定される正規表現にマッチするすべての関数にブレイクポイントを設定します。 このコマンドは、 正規表現にマッチしたすべての関数に無条件ブレイクポイントを設定し、 設定されたすべてのブレイクポイントの一覧を表示します。 設定されたブレイクポイントは、 breakコマンドで設定されたブレイクポイントと同様に扱われます。 他のすべてのブレイクポイントと同様の方法で、 削除、 無効化、 および条件の設定が可能です。 正規表現の構文は、 `grep'のようなツールによって使用される標準的なものです。 シェルによって使用される構文とは異なることに注意してください。 例えば、 foo*は、 foの後ろにゼロ個以上のoが続く部分を含む名前を持つすべての関数にマッチします。 ユーザの指定する正規表現の先頭と末尾には暗黙のうちに.*があるものと想定されますので、 名前の先頭がfooである関数にだけマッチさせたいときは、 ^fooを使ってください。 C++プログラムのデバッグにおいて、 あるオーバーロードされたメンバ関数が、 特別なクラスだけが持つメンバ関数というわけではない場合、 そのメンバ関数にブレイクポイントを設定するのに、 rbreakコマンドは便利です。
info breakpoints [n]
info break [n]
info watchpoints [n]
設定された後、 削除されていない、 すべてのブレイクポイント、 ウォッチポイント、 キャッチポイントの一覧を表示します。 それぞれについて、 以下の情報が表示されます。
ブレイクポイント番号
タイプ
ブレイクポイント、 ウォッチポイント、 または、 キャッチポイント
廃棄
ブレイクポイントに次に到達したときに、 無効化または削除されるべくマークされているか否かを示します。
有効/無効
有効なブレイクポイントを`y'、 有効でないブレイクポイントを`n'で示します。
アドレス
ユーザ・プログラム内のブレイクポイントの位置をメモリ・アドレスとして示します。
対象
ユーザ・プログラムのソース内におけるブレイクポイントの位置を、 ファイル名および行番号で示します。
ブレイクポイントが条件付きのものである場合、 info breakコマンドは、 そのブレイクポイントに関する情報の次の行に、 その条件を表示します。 ブレイクポイント・コマンドがあれば、 続いてそれが表示されます。 info breakコマンドに引数としてブレイクポイント番号nが指定されると、 その番号に対応するブレイクポイントだけが表示されます。 コンビニエンス変数$_、 および、 xコマンドのデフォルトの参照アドレスには、 一覧の中で最後に表示されたブレイクポイントのアドレスが設定されます (メモリの調査参照)。 info breakコマンドは、 ブレイクポイントに到達した回数を表示します。 これは、 ignoreコマンドと組み合わせると非常に便利です。 まず、 ignoreコマンドによってブレイクポイントへの到達をかなりの回数無視するよう設定します。 プログラムを実行し、 info breakコマンドの出力結果から何回ブレイクポイントに到達したかを調べます。 再度プログラムを実行し、 今度は前回の実行時に到達した回数より1だけ少ない回数だけ無視するように設定します。 こうすることで、 前回の実行時にそのブレイクポイントに最後に到達したときと同じ状態でプログラムを停止させることが簡単にできます。

GDBでは、 ユーザ・プログラム内の同一箇所に何度でもブレイクポイントを設定することができます。 これは、 くだらないことでも、 無意味なことでもありません。 設定されるブレイクポイントが条件付きのものである場合、 これはむしろ有用です (ブレイクポイントの成立条件参照)。

GDB自身が、 特別な目的でユーザ・プログラム内部にブレイクポイントを設定することがあります。 例えば、 (Cプログラムにおける) longjmpを適切に処理するためなどです。 これらの内部的なブレイクポイントには-1から始まる負の番号が割り当てられます。 `info breakpoints'コマンドは、 このようなブレイクポイントを表示しません。

これらのブレイクポイントは、 GDBの保守コマンド`maint info breakpoints'で表示することができます。

maint info breakpoints
`info breakpoints'コマンドと同様の形式で呼び出され、 ユーザが明示的に設定したブレイクポイントと、 GDBが内部的な目的で使用しているブレイクポイントの両方を表示します。 内部的なブレイクポイントは、 負のブレイクポイント番号で示されます。 タイプ欄にブレイクポイントの種類が表示されます。
breakpoint
明示的に設定された普通のブレイクポイント
watchpoint
明示的に設定された普通のウォッチポイント
longjmp
longjmpが呼び出されたときに正しくステップ処理ができるように、 内部的に設定されたブレイクポイント
longjmp resume
longjmpのターゲットとなる箇所に内部的に設定されたブレイクポイント
until
GDBのuntilコマンドで一時的に使用される内部的なブレイクポイント
finish
GDBのfinishコマンドで一時的に使用される内部的なブレイクポイント
shlib events
共用ライブラリ・イベント

ウォッチポイントの設定

ウォッチポイントを設定することで、 ある式の値が変化したときに、 プログラムの実行を停止させることができます。 その値の変更が、 プログラムのどの部分で行われるかをあらかじめ知っている必要はありません。

システムによって、 ウォッチポイントがソフトウェアによって実装されていることもあれば、 ハードウェアによって実装されていることもあります。 GDBは、 ユーザ・プログラムをシングル・ステップ実行して、 そのたびに変数の値をテストすることによって、 ソフトウェア・ウォッチポイントを実現しています。 これは、 通常の実行と比較すると、 何百倍も遅くなります。 (それでも、 プログラムのどの部分が問題を発生させたのか全く手掛りのない誤りを見つけることができるのであれば、 十分価値のあることかもしれません)。

HP-UX、 Linux、 および、 その他のいくつかのx86ベースのターゲット上では、 GDBにハードウェア・ウォッチポイントのサポートも組み込まれています。 これを使用すれば、 ユーザ・プログラムの実行が遅くなることはありません。

watch expr
exprで指定される式に対してウォッチポイントを設定します。 プログラムがこの式の値を書き換えるときに、 GDBはプログラムの実行を停止させます。
rwatch expr
exprで指定される対象が読み取りアクセスされるときにプログラムを停止させるウォッチポイントを設定します。
awatch expr
exprで指定される対象が読み取りアクセス、 または、 書き込みアクセスされるときにプログラムを停止させるウォッチポイントを設定します。
info watchpoints
ウォッチポイント、 ブレイクポイント、 キャッチポイントの一覧を表示します。 これは、 info breakと同じです。

GDBは、 可能であれば、 ハードウェア・ウォッチポイントを設定します。 ハードウェア・ウォッチポイントをセットした場合は高速な実行が可能であり、 デバッガは、 変更を引き起こした命令のところで、 値の変更を報告することができます。 ハードウェア・ウォッチポイントを設定できない場合、 GDBは、 ソフトウェア・ウォッチポイントを設定します。 これは、 実行速度も遅く、 値の変更は、 その変更が実際に発生した後に、 その変更を引き起こした命令のところではなく、 1つ後ろの文のところで報告されます

watchコマンドを実行すると、 ハードウェア・ウォッチポイントの設定が可能な場合には、 GDBは、 以下のような報告を行います。

Hardware watchpoint num: expr

現在のところ、 awatchコマンドとrwatchコマンドは、 ハードウェア・ウォッチポイントしかセットすることができません。 これは、 監視対象となっている式の値を変更しないようなデータへのアクセスは、 すべての命令をその実行時に検査することなくしては実現できないからです。 GDBは、 現在のところこのようなことを行っていません。 awatchコマンドやrwatchコマンドでハードウェア・ブレイクポイントをセットできないことが判明すると、 GDBは以下のようなメッセージを出力します。

Expression cannot be implemented with read/access watchpoint.

ときには、 監視対象となる式のデータ型が、 ターゲット・マシン上においてハードウェア・ウォッチポイントが処理できる範囲を超えているために、 GDBがハードウェア・ウォッチポイントをセットできないということが起こり得ます。 例えば、 システムによっては、 4バイトまでの領域しか監視できません。 このようなシステムでは、 (典型的には8バイトである) 倍精度浮動小数点数をもたらす式に対するハードウェア・ウォッチポイントはセットできません。 1つの回避策として、 大きな領域を連続する小さな領域に分割して、 それぞれを別のウォッチポイントによって監視するということは可能であるかもしれません。

ハードウェア・ウォッチポイントをあまりにも数多くセットすると、 プログラムの実行を再開したときに、 GDBがそのすべてを設定することができない可能性があります。 アクティブなウォッチポイントの正確な数は、 プログラムの実行が再開されるその瞬間まで分らないため、 ユーザがウォッチポイントをセットしている最中には、 GDBはこの点について警告を発することができないかもしれません。 以下のような警告が、 プログラムの実行再開時に初めて表示されることになります。

Hardware watchpoint num: Could not insert watchpoint

このようなことが発生した場合は、 ウォッチポイントをいくつか削除するか、 もしくは、 無効にしてください。

SPARClite DSUは、 デバッグ・レジスタに割り当てられた データ・アドレスや命令アドレスにプログラムがアクセスすると、 トラップを発生させます。 データ・アドレスについては、 DSUがwatchコマンドを支援しています。 しかし、 ハードウェアの提供するブレイクポイント・レジスタは、 データ・ウォッチポイントを2つまでしか取れず、 その2つは同じ種類のウォッチポイントでなければなりません。 例えば、 2つのウォッチポイントを、 両方ともwatchコマンドでセットすること、 両方ともrwatchコマンドでセットすること、 あるいは、 両方ともawatchコマンドでセットすることはいずれも可能ですが、 それぞれを異なるコマンドでセットすることはできません。 異なる種類のウォッチポイントを同時にセットしようとしても、 コマンドの実行をGDBが拒否します。 このような場合、 使用しないウォッチポイントを削除または無効化してから、 新しいウォッチポイントをセットしてください。

printcallを使用して関数を対話的に呼び出すと、 それまでにセットされていたウォッチポイントはいずれも、 GDBが別の種類のブレイクポイントに到達するか、 あるいは、 関数の呼び出しが終了するまでの間は、 効果を持たなくなります。

局所(自動)変数を監視するウォッチポイント、 および、 局所(自動)変数を含む式を監視するウォッチポイントは、 それらの変数がスコープの範囲外となったとき、 すなわち、 それらの変数が定義されているブロックの外に実行制御が移ったときに、 GDBが自動的に削除します。 特に、 デバッグ対象のプログラムが終了したときには、 すべての局所変数がスコープの範囲外となるため 広域変数を監視するウォッチポイントだけがセットされた状態で残ります。 プログラムを再実行するのであれば、 これらのウォッチポイントを再度セットする必要があります。 main関数のエントリにブレイクポイントをセットしておいて、 そこに到達した後にすべてのウォッチポイントをセットするという方法があります。

注意:マルチスレッド・プログラムでは、 ウォッチポイントの有用性は限定されます。 現在のウォッチポイントの実装では、 GDBは、 単一スレッド においてしか式の値を監視することができません。 その式の値を変更するのはカレント・スレッドだけであること (かつ、 他のスレッドがカレント・スレッドにはならないこと) が確実であれば、 通常どおりウォッチポイントを使用することができます。 しかし、 カレント・スレッド以外のスレッドが式の値を変更することがあると、 GDBは、 その変更に気付かないかもしれません。

HP-UXにおける注意:マルチスレッド・プログラムでは、 ソフトウェア・ウォッチポイントの有用性は限定されます。 ソフトウェア・ウォッチポイントを生成した場合、 GDBは、 単一スレッド においてしか式の値を監視することができません。 その式の値を変更するのはカレント・スレッドだけであること (かつ、 他のスレッドがカレント・スレッドにはならないことが) 確実であれば、 通常どおりソフトウェア・ウォッチポイントを使用することができます。 しかし、 カレント・スレッド以外のスレッドが式の値を変更することがあると、 GDBは、 その変更に気付かないかもしれません。 (これに対して、 ハードウェア・ウォッチポイントは、 すべてのスレッドにおいて式を監視します。)

キャッチポイントの設定

キャッチポイントを使用することによって、 C++例外や共用ライブラリのローディングのような、 ある種のプログラム・イベントが発生したときに、 デバッガを停止させることができます。 キャッチポイントをセットするには、 catchコマンドを使用します。

catch event
eventで指定されるイベントが発生したときに 停止します。 eventは、 以下のいずれかです。
throw
C++例外の発生。
catch
C++例外のキャッチ。
exec
execの呼び出し。 現在これは、 HP-UXにおいてのみ利用可能です。
fork
forkの呼び出し。 現在これは、 HP-UXにおいてのみ利用可能です。
vfork
vforkの呼び出し。 現在これは、 HP-UXにおいてのみ利用可能です。
load
load libname
任意の共用ライブラリの動的なローディング、 あるいは、 libnameで指定されるライブラリのローディング。 現在これは、 HP-UXにおいてのみ利用可能です。
unload
unload libname
動的にロードされた任意の共用ライブラリのアンローディング、 あるいは、 libnameで指定されるライブラリのアンローディング。 現在これは、 HP-UXにおいてのみ利用可能です。
tcatch event
1回だけ停止させるキャッチポイントを設定します。 最初にイベントが捕捉された後に、 キャッチポイントは自動的に削除されます。

カレントなキャッチポイントの一覧を表示するには、 info breakコマンドを使用します。

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

catchコマンドが、 例外処理をデバッグする手段としては最適なものではないような場合もあります。 どこで例外が発生したのかを正確に知りたい場合、 例外ハンドラが呼び出されるにプログラムを停止させた方がよいでしょう。 なぜなら、 スタック・ポインタの調整が行われる前のスタックの状態を見ることができるからです。 例外ハンドラの内部にブレイクポイントを設定してしまうと、 どこで例外が発生したのかを調べるのは簡単ではないでしょう。

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

    /* addrは例外識別子が格納される領域
       idは例外識別子 */
    void __raise_exception (void **addr, void *id);

スタック・ポインタの調整が行われる前に、 すべての例外をデバッガにキャッチさせるには、 __raise_exceptionにブレイクポイントを設定します (ブレイクポイント、ウォッチポイント、キャッチポイント参照)。

idの値に依存する条件を付けたブレイクポイント (ブレイクポイントの成立条件参照) を使用することで、 特定の例外が発生したときにだけユーザ・プログラムを停止させることができます。 複数の条件付きブレイクポイントを設定することで、 複数の例外の中のどれかが発生したときにユーザ・プログラムを停止させることもできます。

ブレイクポイントの削除

ブレイクポイント、 ウォッチポイント、 キャッチポイントがプログラムを停止させた後、 同じところで再びプログラムを停止させたくない場合、 それらを取り除くことがしばしば必要になります。 これが、 ブレイクポイントの削除と呼ばれるものです。 削除されたブレイクポイントはもはや存在しなくなり、 それが存在したという記録も残りません。

clearコマンドを使用する場合、 ブレイクポイントを、 それがプログラム内部のどこに存在するかを指定することによって削除します。 deleteコマンドの場合は、 ブレイクポイント番号を指定することで、 個々のブレイクポイント、 ウォッチポイント、 キャッチポイントを削除することができます。

ブレイクポイントで停止した後、 先へ進むために、 そのブレイクポイントを削除する必要はありません。 ユーザが実行アドレスを変更することなく継続実行する場合、 最初に実行される命令に設定されているブレイクポイントを、 GDBは自動的に無視します。

clear
選択されているスタック・フレーム内において次に実行される命令にセットされているブレイクポイントを削除します (フレームの選択参照)。 最下位にあるフレームが選択されている場合、 ユーザ・プログラムが停止した箇所にセットされているブレイクポイントを削除するのに便利な方法です。
clear function
clear filename:function
functionで指定される関数のエントリにセットされているブレイクポイントを削除します。
clear linenum
clear filename:linenum
指定された行、 または、 その行内に記述されたコードにセットされたブレイクポイントを削除します。
delete [breakpoints] [range...]
引数で指定された範囲内にあるブレイクポイント、 ウォッチポイント、 キャッチポイントを削除します。 引数が指定されない場合、 すべてのブレイクポイントを削除します (set confirm offコマンドが事前に実行されていない場合、 GDBは、 削除してもよいかどうか確認を求めてきます)。 このコマンドの省略形は dです。

ブレイクポイントの無効化

ブレイクポイント、 ウォッチポイント、 キャッチポイントを削除するのではなく、 無効化したい場合もあるでしょう。 無効化によってブレイクポイントは、 それがあたかも削除されたかのように機能しなくなりますが、 後に再度有効化することができるよう、 そのブレイクポイントに関する情報は記憶されます。

ブレイクポイント、 ウォッチポイント、 キャッチポイントは、 enableコマンドとdisableコマンドによって有効化、 無効化されます。 これらのコマンドには、 引数として1つ以上のブレイクポイント番号を指定することも可能です。 指定すべき番号が分からない場合は、 info breakコマンド、 または、 info watchコマンドによってブレイクポイント、 ウォッチポイント、 キャッチポイントの一覧を表示させてください。

ブレイクポイント、 ウォッチポイント、 キャッチポイントは、 有効/無効という観点から見て、 4つの異なる状態を持つことができます。

以下のコマンドを使用することで、 ブレイクポイント、 ウォッチポイント、 キャッチポイントの有効化、 無効化が可能です。

disable [breakpoints] [range...]
指定されたブレイクポイントを無効化します。 番号が1つも指定されない場合は、 すべてのブレイクポイントが無効化されます。 無効化されたブレイクポイントは何ら影響力を持ちませんが、 そのブレイクポイントに関する情報まで削除されるわけではありません。 そのブレイクポイントを無視する回数、 ブレイクポイント成立の条件、 ブレイクポイント・コマンドなどのオプションは、 後にそのブレイクポイントが有効化される場合に備えて、 記憶されています。 disableコマンドは disと省略することができます。
enable [breakpoints] [range...]
指定されたブレイクポイント (または、 すべての定義済みブレイクポイント) を有効化します。 有効化されたブレイクポイントは、 再びユーザ・プログラムを停止させることができるようになります。
enable [breakpoints] once range...
指定されたブレイクポイントを一時的に有効化します。 このコマンドで有効化されたブレイクポイントはどれも、 最初にプログラムを停止させた直後に、 GDBによって無効化されます。
enable [breakpoints] delete range...
1回だけプログラムを停止させ、 その直後に削除されるような設定で、 指定されたブレイクポイントを有効化します。 このコマンドで有効化されたブレイクポイントはどれも、 最初にプログラムを停止させた直後に、 GDBによって削除されます。

tbreakコマンド (ブレイクポイントの設定参照) でセットされたブレイクポイントを除き、 ユーザによってセットされたブレイクポイントの初期状態は有効状態です。 その後、 ユーザが上記のコマンドのいずれかを使用した場合に限り、 無効化されたり有効化されたりします (untilコマンドは、 独自にブレイクポイントをセット、 削除することができますが、 ユーザのセットした他のブレイクポイントの状態は変更しません。 継続実行とステップ実行 を参照してください)。

ブレイクポイントの成立条件

最も単純なブレイクポイントは、 指定された箇所にプログラムが到達するたびに、 プログラムの実行を停止させます。 ブレイクポイントに対して条件を指定することも可能です。 ここで、 「条件」とは、 プログラムが記述された言語で表現された真偽値を表わす式のことです (参照)。 条件付きのブレイクポイントにプログラムが到達するたびに、 その式が評価されます。 そして、 その結果がであった場合だけ、 プログラムは停止します。

これは、 プログラムの正当性を検査するために診断式を使用するのとは逆になります。 診断式の場合は、 成立しないとき、 すなわち条件が偽であるときに、 プログラムを停止させます。 C言語でassertという診断式をテストするためには、 しかるべきブレイクポイントに`! assert'という条件を設定します。

ウォッチポイントに対して条件を設定することもできます。 もともとウォッチポイントは、 ある式の値を検査するものですから、 これは必要ないかもしれません。 しかし、 ある変数の新しい値がある特定の値に等しいか検査するのは条件式のほうに任せて、 ウォッチポイントの対象そのものは単にその変数の名前にしてしまうという設定の方が簡単でしょう。

ブレイクポイントの成立条件に副作用を持たせたり、 場合によってはプログラム内部の関数を呼び出させたりすることもできます。 プログラムの進行状況をログに取る関数を呼び出したり、 特別なデータ構造をフォーマットして表示するユーザ定義の関数を使用したい場合などに便利です。 この効果は、 同じアドレスに有効なブレイクポイントが別に設定されていない限り、 完全に予測可能です (別のブレイクポイントが設定されていると、 GDBはこのブレイクポイントを先に検出し、 他のブレイクポイントで設定した条件式をチェックすることなくプログラムを停止させてしまうかもしれません)。 あるブレイクポイントに到達したときに副作用を持つ処理を実行させるためには、 ブレイクポイントに条件を設定するよりも、 ブレイクポイント・コマンドを使用する方が便利であり、 柔軟でしょう (ブレイクポイント・コマンド・リスト参照)。

ブレイクポイントの成立条件は、 ブレイクポイントをセットする際に、 breakコマンドの引数に`if'を使用することによって設定できます。 ブレイクポイントの設定 を参照してください。 ブレイクポイントの成立条件は、 conditionコマンドによっていつでも変更できます。

watchコマンドの中で ifキーワードを使用することもできます。 catchコマンドは、 ifキーワードを認識しません。 キャッチポイントに対して条件を追加設定する唯一の方法は、 conditionコマンドを使うことです。

condition bnum expression
bnumで指定される番号のブレイクポイント、 ウォッチポイント、 キャッチポイントの成立条件として、 expressionを指定します。 条件をセットした後、 番号bnumのブレイクポイントは、 expressionの値が真 (C言語の場合はゼロ以外の値) であるときのみ、 ユーザ・プログラムを停止させます。 conditionコマンドを使用すると、 GDBはただちにexpressionの構文の正当性、 および、 expressionの中で使用されるシンボル参照の、 ブレイクポイントのコンテキストにおける有効性をチェックします。 expressionが、 ブレイクポイントのコンテキストにおいて参照できないシンボルを使用していると、 GDBは以下のようなエラー・メッセージを表示します。
No symbol "foo" in current context.
conditionコマンド (あるいは、 break if ...のように条件付きでブレイクポイントをセットするコマンド) が実行されるときに、 expressionの値がGDBによって実際に評価されるわけではありません。 を参照してください。
condition bnum
bnumで指定される番号のブレイクポイントから条件を削除します。 実行後、 それは通常の無条件ブレイクポイントになります。

ブレイクポイント成立条件の特別なものに、 ブレイクポイントに到達した回数がある数に達したときにプログラムを停止させるというものがあります。 これは大変便利なので、 それを実現するための特別な方法が提供されています。 それは、 ブレイクポイントの通過カウント (ignore count) を使用する方法です。 すべてのブレイクポイントは、 通過カウントと呼ばれる整数値を持っています。 ほとんどの場合、 この通過カウントの値はゼロであり、 何ら影響力を持ちません。 しかし、 通過カウントとして正の値を持つブレイクポイントに到達すると、 ユーザ・プログラムはそこで停止せず、 単に通過カウントの値を1だけ減少させて処理を継続します。 したがって、 通過カウントがnであると、 ユーザ・プログラムがそのブレイクポイントに到達した回数がn以下の間は、 そのブレイクポイントにおいてプログラムは停止しません。

ignore bnum count
bnumで指定される番号のブレイクポイントの通過カウントをcountで指定される値にセットします。 ブレイクポイントへの到達回数がcount以下の間、 ユーザ・プログラムは停止しません。 この間、 GDBは、 通過カウントの値を減少させる以外には何もしません。 次にブレイクポイントに到達したときにプログラムを停止させるには、 countにゼロを指定してください。 ブレイクポイントで停止した後にcontinueコマンドを使用して実行を再開する場合、 ignoreコマンドを使用することなく、 直接continueコマンドの引数に通過カウントを指定することができます。 継続実行とステップ実行 を参照してください。 ブレイクポイントが通過カウントとして正の値を持ち、 かつ、 成立条件を持つ場合、 成立条件はチェックされません。 通過カウントが0に達すると、 GDBは成立条件のチェックを再開します。 `$foo-- <= 0'のように、 評価のたびに値の減少するコンビニエンス変数を使用した評価式によって、 通過カウントと同様の効果を達成することができます。 コンビニエンス変数 を参照してください。

通過カウントは、 ブレイクポイント、 ウォッチポイント、 キャッチポイントに適用されます。

ブレイクポイント・コマンド・リスト

ブレイクポイント (あるいは、 ウォッチポイント、 キャッチポイント) に対して、 それによってプログラムが停止したときに実行される一連のコマンドを指定することができます。 例えば、 ある特定の式の値を表示したり、 他のブレイクポイントを有効化したりできると便利なこともあるでしょう。

commands [bnum]
... command-list ...
end
bnumで指定される番号を持つブレイクポイントに対して一連のコマンドを指定します。 コマンド自体は、 次の行以下に記述します。 コマンドの記述を終了するには、 endだけから成る1行を記述します。 ブレイクポイントからすべてのコマンドを削除するには、 commands行に続いて (コマンドを1つも指定せずに) endを記述します。 引数bnumが指定されない場合、 commandsは、 最後にセットされたブレイクポイント、 ウォッチポイント、 キャッチポイントを対象とします (最後に到達したブレイクポイントではありません)。

command-listの記述中は、 RETキーが持つ、 最後に実行されたコマンドを繰り返し実行する機能は無効です。

ブレイクポイント・コマンドを使用してプログラムの実行を再開することができます。 continuestep、 または、 実行を再開させるその他の任意のコマンドを使用してください。

コマンド・リストの中で、 実行を再開するコマンドの後に記述されているものは無視されます。 というのは、 プログラムが実行を再開すると (たとえそれがnextコマンドやstepコマンドによるものであっても) 別のブレイクポイントに到達する可能性があり、 そのブレイクポイントがコマンド・リストを持っていると、 どちらのリストを実行するべきかあいまいになるからです。

コマンド・リストの先頭に指定されたコマンドがsilentであると、 ブレイクポイントで停止したときに通常出力されるメッセージは表示されません。 これは、 ある特定のメッセージを出力して実行を継続するようなブレイクポイントをセットするのに望ましいでしょう。 コマンド・リスト中の後続のコマンドがどれもメッセージを出力しない場合、 ブレイクポイントに到達したことをユーザに示す情報は何も表示されないことになります。 silentはブレイクポイント・コマンド・リストの先頭においてのみ意味を持ちます。

echooutputprintfの各コマンドを使用することで、 細かく管理された出力を表示することができます。 これらのコマンドは、 silent指定のブレイクポイントで使うと便利です。 制御された出力を得るためのコマンド を参照してください。

例えば、 ブレイクポイント・コマンドを使用して、 fooへのエントリにおいて xが正の値を持つときに、 その値を表示するには以下のようにします。

break foo if x>0
commands
silent
printf "x is %d\n",x
cont
end

ブレイクポイント・コマンドの1つの応用として、 あるバグの持つ影響を取り除いて、 他のバグを見つけるためにテストを継続することができます。 誤りのある行の次の行に、 誤りの発生を検出するような条件付きのブレイクポイントをセットし、 ブレイクポイント・コマンドの中で修正の必要な変数に正しい値を割り当てます。 コマンド・リストの最後にはcontinueコマンドを記述して、 プログラムが停止しないようにします。 また、 プログラムの先頭にはsilentコマンドを記述し、 何も出力されないようにします。 以下に例を挙げます。

break 403
commands
silent
set x = y + 4
cont
end

ブレイクポイント・メニュー

プログラミング言語によっては (特にC++の場合)、 異なるコンテキストにおいて使用するために、 同一の関数名を複数回定義することが可能です。 これは、 オーバーローディングと呼ばれます。 関数名がオーバーロードされている場合、 `break function'だけでは、 どこにブレイクポイントをセットしたいのかをGDBに正しく通知するのに十分ではありません。 このような場合には、 ブレイクポイントをセットしたい関数がどれであるかを正確に指定するために、 `break function(types)'のような形式を使用することができます。 このような形式を使用しないと、 GDBは候補となりえるブレイクポイントの一覧を番号付きのメニューとして表示し、 プロンプト`>'によってユーザの選択を待ちます。 先頭の2つの選択肢は常に、 `[0] cancel'`[1] all'です。 1を入力すると、 候補となるすべての関数のそれぞれの定義に対してブレイクポイントをセットします。 また、 0を入力すると、 新たにブレイクポイントを設定することなく breakコマンドを終了します。

例えば、 以下に示すセッションの抜粋は、 オーバーロードされたシンボルString::afterに対してブレイクポイントをセットしようとした場合を示しています。 ここでは、 この関数名を持つ関数定義の中から3つを選択しています。

(gdb) b String::after
[0] cancel
[1] all
[2] file:String.cc; line number:867
[3] file:String.cc; line number:860
[4] file:String.cc; line number:875
[5] file:String.cc; line number:853
[6] file:String.cc; line number:846
[7] file:String.cc; line number:735
> 2 4 6
Breakpoint 1 at 0xb26c: file String.cc, line 867.
Breakpoint 2 at 0xb344: file String.cc, line 875.
Breakpoint 3 at 0xafcc: file String.cc, line 846.
Multiple breakpoints were set.
Use the "delete" command to delete unwanted
 breakpoints.
(gdb)

挿入できないブレイクポイント

オペレーティング・システムによっては、 他のプロセスがプログラムを実行中は、 そのプログラムにおいてブレイクポイントを使用できないことがあります。 このような状況においてブレイクポイントをセットしてプログラムの実行を開始したり継続したりしようとすると、 GDBは以下のようなエラー・メッセージを表示します。

Cannot insert breakpoints.
The same program may be running in another process.

この状況では、 3つの選択肢があります。

  1. ブレイクポイントを削除または無効化してから処理を継続します。
  2. GDBの実行を中断し、 プログラム・ファイルをコピーして新しい名前を付けます。 GDBの実行を再開し、 exec-fileコマンドを使用して、 新しい名前のプログラムを実行すべきことをGDBに知らせます。 プログラムを再度実行します。
  3. プログラムを再リンクします。 その際、 リンカのオプション`-N'を使用して、 テキスト・セグメントを共用不可とします。 オペレーティング・システムの制約は、 共用不可の実行ファイルの場合は無関係である可能性があります。

ハードウェアによるブレイクポイントやウォッチポイントをあまりにもたくさんアクティブにしようとすると、 これと似たメッセージが出力されることがあります。

Stopped; cannot insert breakpoints.
You may have requested too many hardware breakpoints and watchpoints.

このメッセージは、 プログラムの実行を再開しようと試みたときに表示されます。 何個のブレイクポイントとウォッチポイントが必要になるかは、 GDBにもそのときまで正確には分からないからです。

このメッセージが表示された場合、 ハードウェアによるブレイクポイント、 ウォッチポイントをいくつか無効化または削除してから実行を継続する必要があります。

継続実行とステップ実行

継続実行とは、 ユーザ・プログラムの実行を再開して、 それが正常に終了するまで実行させることを指します。 一方、 ステップ実行とは、 ユーザ・プログラムを1「ステップ」だけ実行することを指します。 ここで「ステップ」とは、 (使用されるコマンドによって) 1行のソース・コードを指すこともありますし、 1マシン命令を指すこともあります。 継続実行の場合でもステップ実行の場合でも、 ブレイクポイントやシグナルが原因となって、 正常終了する前にユーザ・プログラムが停止することがあります (シグナルによってプログラムが停止した場合、 実行を再開するには handleコマンドまたは`signal 0' コマンドを使用するとよいでしょう。 シグナル を参照してください)。

continue [ignore-count]
c [ignore-count]
fg [ignore-count]
ユーザ・プログラムが最後に停止した箇所から、 プログラムの実行を再開します。 停止箇所に設定されているブレイクポイントは無視されます。 引数ignore-countを指定すれば、 停止箇所のブレイクポイントを無視する回数を指定することができます。 これはignoreコマンドと似た効果を持ちます (ブレイクポイントの成立条件参照)。 引数ignore-countは、 ユーザ・プログラムがブレイクポイントによって停止した場合にのみ意味を持ちます。 これ以外の場合には、 continueコマンドへの引数は無視されます。 cおよびfgは、 簡便さのためだけに提供されている同義コマンドで、 continueコマンドと全く同様の動作をします (fgforegroundを省略したものです。 デバッグ対象のプログラムはフォアグラウンド・プログラムであると判断されます)。

別の箇所で実行を再開するには、 呼び出し関数に戻るreturnコマンド (関数からの復帰参照)、 または、 ユーザ・プログラム内の任意の箇所へ移動するjumpコマンド (異なるアドレスにおける処理継続参照) を使用することができます。

ステップ実行を使用する典型的なテクニックは、 問題があると思われる関数やプログラム部分の先頭にブレイクポイント (ブレイクポイント、ウォッチポイント、キャッチポイント参照) を設定し、 ブレイクポイントで停止するまでプログラムを実行させた後、 問題が再現するまで、 関連しそうな変数の値を調べながら、 疑わしい部分を1行ずつ実行することです。

step
異なるソース行に到達するまでユーザ・プログラムを継続実行した後、 プログラムを停止させ、 GDBに制御を戻します。 このコマンドの省略形はsです。

注意:デバッグ情報なしでコンパイルされた関数の内部にいるときにstepコマンドを使用すると、 デバッグ情報付きの関数に達するまでプログラムの実行は継続されます。 同様に、 stepコマンドがデバッグ情報なしでコンパイルされた関数の内部へ入って、 停止することはありません。 デバッグ情報を持たない関数の内部でステップ実行を行うには、 後述のstepiコマンドを使用してください。

stepコマンドは、 ソース・コード行の最初の命令においてのみ停止します。 これにより、 switch文やfor文などにおいて複数回停止してしまうという問題が回避されます。 同じ行の中にデバッグ情報を持つ関数への呼び出しがあると、 stepコマンドは続けて停止します。 すなわち、 その行の中から呼び出されている関数の内部においてステップ実行を行います。 さらにstepコマンドは、 関数が行番号情報を持つ場合に限り、 その関数内部に入り込みます。 関数が行番号情報を持たない場合、 stepコマンドはnextコマンドと同様の動作をします。 これにより、 MIPSマシン上でcc -glを使用すると発生する問題が回避されます。 以前のバージョンにおけるstepコマンドは、 関数が何らかのデバッグ情報を持っていれば、 その内部に入り込んでいました。
step count
stepコマンドによるステップ実行をcount回繰り返します。 ステップ実行をcount回繰り返し終わる前に、 ブレイクポイントに到達するか、 あるいは、 ステップ実行とは関連のないシグナルが発生した場合には、 ただちにステップ実行を中断して停止します。
next [count]
カレントな (最下位の) スタック・フレーム上において、 ソース・コード上の次の行まで実行します。 これはstepコマンドと似ていますが、 nextコマンドは、 ソース・コード上に関数呼び出しが存在すると、 その関数を停止することなく最後まで実行します。 プログラムが停止するのは、 nextコマンドを実行したときと同一のスタック・フレーム上において、 ソース・コード上の異なる行まで実行が継続されたときです。 このコマンドの省略形はnです。 引数countは、 stepコマンドの場合と同様、 繰り返し回数です。 nextコマンドは、 ソース・コード行の最初の命令においてのみ停止します。 これにより、 switch文やfor文などにおいて複数回停止してしまうという問題が回避されます。
finish
選択されているスタック・フレーム上の関数が復帰するまで、 実行を継続します。 戻り値があれば、 それを表示します。 returnコマンド (関数からの復帰参照) と比較してみてください。
until
u
カレントなスタック・フレーム上において、 カレント行よりも後ろにある行に到達するまで実行を継続します。 このコマンドは、 ループ内において複数回ステップ実行をするのを回避するために使用されます。 これはnextコマンドに似ていますが、 唯一の相違点は、 untilコマンドによる実行によってジャンプ命令に到達した場合、 プログラム・カウンタの値がジャンプ命令のアドレスより大きくなるまで、 プログラムが継続実行されるという点です。 これは、 ステップ実行によってループ内の最後の行に到達した後にuntilコマンドを実行することで、 ループから抜け出るまでプログラムを継続実行させることができるということを意味しています。 これに対して、 ループ内の最後の行でnextコマンドを実行すると、 プログラムはループの先頭に戻ってしまうので、 ループ内の処理を繰り返すことを余儀なくされます。 untilコマンドの実行により、 プログラムがカレントなスタック・フレームから抜け出ようとすると、 そこでuntilコマンドはプログラムを停止します。 実行されるマシン・コードの順序がソース行の順序と一致しない場合、 untilコマンドは直観にいくらか反するような結果をもたらすかもしれません。 例えば、 以下に挙げるデバッグ・セッションからの抜粋では、 fframe) コマンドによって、 プログラムが206行目において停止していることが示されています。 ところが、 untilコマンドを実行すると、 195行目で停止してしまいます。
(gdb) f
#0  main (argc=4, argv=0xf7fffae8) at m4.c:206
206                 expand_input();
(gdb) until
195             for ( ; argc > 0; NEXTARG) {
これは、 コンパイラが、 実行の効率を高めるために、 C言語では forループ本体の前に記述されているループ終了のための条件判定を、 ループの先頭ではなく末尾で行うコードを生成したためです。 この判定式にまで処理が進んだとき、 untilコマンドはあたかもループの先頭に戻ったかのように見えます。 しかしながら、 実際のマシン・コードのレベルでは、 前の命令に戻ったわけではありません。 引数のないuntilコマンドは、 1命令ごとのステップ実行によって実現されるため、 引数付きの untilコマンドに比べて処理速度が遅くなります。
until location
u location
locationで指定される箇所に到達するか、 カレントなスタック・フレームを抜け出るまで、 ユーザ・プログラムを継続実行します。 locationbreakコマンドが受け付ける形式の引数です (ブレイクポイントの設定参照)。 この形式によるuntilコマンドはブレイクポイントを使用するため、 引数のないuntilコマンドより処理速度が速くなります。
stepi
stepi arg
si
1マシン命令を実行した後、停止してデバッガに戻ります。 マシン命令単位でステップ実行する場合、 `display/i $pc'を使用すると便利なことがしばしばあります。 これは、 ユーザ・プログラムが停止するたびに、 次に実行される命令をGDBに自動的に表示させます。 自動表示 を参照してください。 引数として、 stepコマンドと同様、 繰り返し回数を取ります。
nexti
nexti arg
ni
1マシン命令を実行しますが、 それが関数の呼び出しである場合は、 関数から復帰するまで実行を継続します。 引数として、nextコマンドと同様、 繰り返し回数を取ります。

シグナル

シグナルは、 プログラム内で発生する非同期イベントです。 オペレーティング・システムによって、 使用可能なシグナルの種類が定義され、 それぞれに名前と番号が割り当てられます。 例えば、 UNIXにおいては、 割り込み文字 (通常は、Ctrlキーを押しながらCを押す) を入力したときにプログラムが受信する SIGINT、 その使用領域からかけ離れたメモリ域を参照したときにプログラムが受信するSIGSEGV、 アラームのタイムアウト時に発生する (プログラムからアラームを要求した場合にのみ発生する) SIGALRMシグナルなどがあります。

SIGALRMなど、 いくつかのシグナルは、 プログラムの正常な機能の一部です。 SIGSEGVなどの他のシグナルは、 エラーを意味します。 これらのシグナルは、 プログラムが事前にそれを処理する何らかの方法を指定しないと、 致命的な (プログラムを即座に終了させる) ものとなります。 SIGINTはユーザ・プログラム内部のエラーを意味するものではありませんが、 通常は致命的なものであり、 割り込みの目的であるプログラムの終了を実現することができます。

GDBは、 ユーザ・プログラム内部における任意のシグナル発生を検出することができます。 ユーザは、 個々のシグナルの発生時に何を実行するかを、 GDBに対して事前に指定することができます。

通常GDBは、 SIGALRMのようなエラーではないシグナルを無視するよう (これらのシグナルがユーザ・プログラムの中で持っている役割を妨害することのないよう) 設定されています。 その一方で、 エラーのシグナルが発生した場合にはすぐにユーザ・プログラムを停止させるよう設定されています。 これらの設定はhandleコマンドによって変更することができます。

info signals
info handle
すべてのシグナルを一覧にして表示します。 また、 個々のシグナルについて、 GDBがそれをどのように処理するよう設定されているかを表示します。 このコマンドを使用して、 定義済みのすべてのシグナルのシグナル番号を知ることができます。 info handleinfo signalsの別名です。
handle signal keywords...
GDBがsignalによって指定されるシグナルを処理する方法を変更します。 signalには、 シグナル番号またはシグナル名称 (先頭の`SIG'は省略可能) を指定します。 キーワードkeywordsによって、 どのように変更するかを指定します。

handleコマンドが受け付けるキーワードには省略形を使用することができます。 省略しない場合、 キーワードは以下のようになります。

nostop
GDBに対して、 このシグナルが発生してもユーザ・プログラムを停止しないよう指示します。 GDBは、 シグナルを受信したことをメッセージ出力によってユーザに通知することができます。
stop
GDBに対して、 このシグナルが発生するとユーザ・プログラムを停止するよう指示します。 これは、 printキーワードを暗黙のうちに含みます。
print
GDBに対して、 このシグナルが発生するとメッセージを表示するよう指示します。
noprint
GDB に対して、 このシグナルが発生したことを知らせないよう指示します。 これは、 nostopキーワードを暗黙のうちに含みます。
pass
GDBに対して、 このシグナルの発生をユーザ・プログラムが検出できるようにするよう指示します。 ユーザ・プログラムはシグナルを処理することができます。 致命的なシグナルが処理されない場合、 ユーザ・プログラムは停止するかもしれません。
nopass
GDBに対して、 このシグナルの発生をユーザ・プログラムが検出できないようにするよう指示します。

シグナルによってユーザ・プログラムが停止した場合、 実行を継続するまでそのシグナルは検出されません。 その時点において、 そのシグナルに対してpassキーワードが有効であれば、 ユーザ・プログラムは、 実行継続時にシグナルを検出します。 言い換えれば、 GDBがシグナルの発生を報告してきたとき、 handleコマンドにpassキーワードまたはnopassキーワードを指定することで、 実行を継続したときにプログラムにそのシグナルを検出させるか否かを制御することができます。

また、 signalコマンドを使用することによって、 ユーザ・プログラムがシグナルを検出できないようにしたり、 通常は検出できないシグナルを検出できるようにしたり、 あるいは任意の時点で任意のシグナルをユーザ・プログラムに検出させたりすることができます。 例えば、 ユーザ・プログラムが何らかのメモリ参照エラーによって停止した場合、 ユーザは、 さらに実行を継続しようとして、 問題のある変数に正しい値を設定して継続実行しようとするかもしれません。 しかし、 実行継続直後に検出される致命的なシグナルのために、 おそらくユーザ・プログラムはすぐに終了してしまうでしょう。 このようなことを回避したければ、 `signal 0'コマンドによって実行を継続することができます。 ユーザ・プログラムへのシグナルの通知 を参照してください。

マルチスレッド・プログラムの停止と起動

ユーザ・プログラムが複数のスレッド (マルチスレッド・プログラムのデバッグ参照) を持つ場合、 すべてのスレッドにブレイクポイントを設定するか、 特定のスレッドにブレイクポイントを設定するかを選択することができます。

break linespec thread threadno
break linespec thread threadno if ...
linespecはソース行を指定します。 記述方法はいくつかありますが、 どの方法を使っても結果的にはソース行を指定することになります。 breakコマンドに修飾子`thread threadno'を使用することで、 ある特定のスレッドがこのブレイクポイントに到達したときだけGDBがプログラムを停止するよう、 指定することができます。 ここでthreadnoは、 GDBによって割り当てられるスレッド識別番号で、 `info threads'コマンドによる出力の最初の欄に表示されるものです。 ブレイクポイントをセットする際に`thread threadno'を指定しなければ、 そのブレイクポイントはユーザ・プログラム内部のすべてのスレッドに適用されます。 条件付きのブレイクポイントに対してもthread識別子を使用することができます。 この場合、 以下のように`thread threadno'をブレイクポイント成立条件の前に記述してください。
(gdb) break frik.c:13 thread 28 if bartab > lim

いかなる理由によるのであれGDB配下においてユーザ・プログラムが停止した場合、 カレント・スレッドだけではなく、 すべての実行スレッドが停止します。 これにより、 知らないうちに状態の変化が発生することを心配することなく、 スレッドの切り替えも含めて、 プログラム全体の状態を検査することができます。

逆に、 プログラムの実行を再開したときには、 すべてのスレッドが実行を開始します。 これは、 stepコマンドやnextコマンドによるシングル・ステップ実行の場合でも同様です。

特にGDBは、 すべてのスレッドの歩調を合わせてシングル・ステップ実行することはできません。 スレッドのスケジューリングは、 デバッグ対象のマシンのオペレーティング・システムに依存する (GDBが管理するわけではない) ので、 カレント・スレッドがシングル・ステップの実行を完了する前に、 他のスレッドは複数の文を実行してしまうかもしれません。 また、 プログラムが停止するとき、 他のスレッドは2つの文の間の境界のところでぴったり停止するよりも、 文の途中で停止してしまう方が一般的です。

また、 継続実行やステップ実行の結果、 プログラムが別のスレッド内で停止してしまうこともありえます。 最初のスレッドがユーザの要求した処理を完了する前に、 他のスレッドがブレイクポイントに到達した場合、 シグナルを受信した場合、 例外が発生した場合には、 常にこのようなことが発生します。

OSによっては、 OSスケジューラをロックすることによって、 ただ1つのスレッドだけが実行されるようにすることができます。

set scheduler-locking mode
スケジューラのロッキング・モード(locking mode)を設定します。 offの場合は、 ロックのメカニズムは機能せず、 任意の時点において、 どのスレッドも実行される可能性を持ちます。 onの場合は、 再始動(resume)されるスレッドの優先順位が低い場合には、 カレント・スレッドだけが実行を継続することができます。 stepモードでは、 シングル・ステップ実行のための最適化が行われます。 ステップ実行をしている間、 他のスレッドが「プロンプトを横取りする」ことがないよう、 カレント・スレッドに占有権が与えられます。 また、 ステップ実行をしている間、 他のスレッドはきわめて稀にしか (あるいは、 まったく) 実行するチャンスを与えられません。 nextコマンドによって関数呼び出しの次の行まで処理を進めると、 他のスレッドが実行される可能性は高くなります。 また、 continueuntilfinishのようなコマンドを使用すると、 他のスレッドは 完全に自由に実行されることになります。 しかし、 そのタイムスライスの中でブレイクポイントに到達しない限り、 他のスレッドが、 デバッグの対象となっているスレッドから、 GDBプロンプトを横取りすることはありません。
show scheduler-locking
スケジューラの現在のロッキング・モードを表示します。


[Contents]   [Back]   [Prev]   [Up]   [Next]   [Forward]