デバッガを使用する主要な目的は、
プログラムが終了してしまう前に停止させたり、
問題のあるプログラムを調査して何が悪いのかを調べたりすることにあります。
GDB内部においてプログラムが停止する理由はいくつかあります。
例えば、
シグナルの受信、
ブレイクポイントへの到達、
step
コマンド実行後の新しい行への到達などです。
プログラムが停止すると、
変数の値の調査や設定、
新しいブレイクポイントの設定、
既存のブレイクポイントの削除などを行った後、
プログラムの実行を継続することができます。
通常、
GDBが表示するメッセージは、
ユーザ・プログラムの状態について多くの情報を提供してくれます。
ユーザはいつでも明示的にこれらの情報を要求することができます。
info program
ブレイクポイントによって、
プログラム内のある特定の箇所が実行されるときに、
プログラムを停止することができます。
個々のブレイクポイントについて、
そのブレイクポイントにおいてプログラムを停止させるために満足されなければならない、
より詳細な条件を設定することができます。
ブレイクポイントの設定は、
一連のbreak
コマンドのいずれかによって行います
(ブレイクポイントの設定を参照)。
行番号、
関数名、
プログラム内のアドレスを指定することで、
プログラムのどこで停止するかを指定することができます。
例外処理機能を持つ言語
(例えば、
GNU C++)
では、
例外の発生箇所にブレイクポイントを設定することもできます
(ブレイクポイントと例外を参照)。
SunOS 4.x、
SVR4、
Alpha OSF/1上では、
実行開始前に共用ライブラリ内にブレイクポイントを設定することもできます。
ウォッチポイントは、
ある式の値が変化したときにユーザ・プログラムを停止させる、
特別なブレイクポイントです。
ウォッチポイントは、
他のブレイクポイントと同じように管理することができますが、
ウォッチポイントの設定だけは別のコマンドで行います
(ウォッチポイントの設定を参照)。
ブレイクポイントおよびウォッチポイントの有効化、
無効化、
削除に使用するコマンドは同一です。
ブレイクポイントでGDBが停止したときには常に、
自動的にユーザ・プログラム内のある値を表示させるようにすることができます。
自動表示を参照してください。
ユーザが新規に作成した個々のブレイクポイントおよびウォッチポイントに、
GDBは番号を割り当てます。
この番号は1から始まる連続する整数値です。
ブレイクポイントの様々な側面を制御するコマンドの多くにおいて、
ユーザは変更を加えたいブレイクポイントを指定するのにこの番号を指定します。
個々のブレイクポイントを有効化、
無効化することができます。
無効化されたブレイクポイントは、
再度有効化されるまで、
ユーザ・プログラムの実行に影響を与えません。
ブレイクポイントはbreak
コマンド
(省略形はb
)
によって設定されます。
デバッガのコンビニエンス変数`$bpnum'に、
ユーザが最後に設定したブレイクポイントの番号が記録されます。
コンビニエンス変数の使用方法については、
コンビニエンス変数を参照してください。
ブレイクポイントの設定箇所を指定する方法はいくつかあります。
break function
break +offset
break -offset
break linenum
break filename:linenum
break filename:function
break *address
break
break
コマンドは選択されたスタック・フレーム内において次に実行される命令にブレイクポイントを設定します
(スタックの検査を参照)。
最も内側のスタック・フレーム以外のフレームが選択されていると、
このブレイクポイントは、制御が現在のフレームに戻ってきた時点で、
ユーザ・プログラムを停止させます。
これが持つ効果は、
選択されたフレーム内部のフレームにおいて
finish
コマンドを実行するのと似ています。
ただし、
1つ異なるのは、
finish
コマンドがアクティブなブレイクポイントを残さないという点です。
最も内側のスタック・フレームにおいて引数なしで
break
コマンドを実行した場合、
現在停止している箇所に次に到達したときに、
GDBはユーザ・プログラムを停止させます。
これは、
ループの内部では便利でしょう。
GDBは通常、
実行を再開したときに、
最低でも1命令が実行されるまでの間は、
ブレイクポイントの存在を無視します。
そうでなければ、
ブレイクポイントで停止した後、
そのブレイクポイントを無効にしない限り、
先へ進めないことになってしまいます。
この規則は、
ユーザ・プログラムが停止したときに、
そのブレイクポイントが存在したか否かにかかわらず、
適用されます。
break ... if cond
tbreak args
break
コマンドと同様であり、
ブレイクポイントも同様に設定されますが、
tbreak
により設定されたブレイクポイントは、
プログラムが最初にそこで停止した後に自動的に削除されます。
ブレイクポイントの無効化を参照してください。
hbreak args
break
コマンドと同様であり、
ブレイクポイントも同様に設定されますが、
hbreak
により設定されるブレイクポイントはハードウェアによるサポートを必要とします。
ターゲット・ハードウェアによっては、
このような機能を持たないものもあるでしょう。
これが目的とするところは、
EPROM/ROMコードのデバッグであり、
ユーザはある命令にブレイクポイントを設定するのに、
その命令を変更する必要がありません。
これは、
SPARClite DSUの提供するトラップ発生機能と一緒に使用することができます。
DSUは、
デバッグ・レジスタに割り当てられた
データ・アドレスあるいは命令アドレス
をプログラムがアクセスすると、
トラップを発生させます。
ハードウェアの提供するブレイクポイント・レジスタは、
データ・ブレイクポイントを2つまでしか取れないので、
このコマンドが3つ以上使用しようとすると、
GDBはそれを拒絶します。
このような場合、
不要になったハードウェア・ブレイクポイントを削除もしくは無効化してから、
新しいハードウェア・ブレイクポイントを設定してください。
ブレイクポイントの成立条件を参照してください。
thbreak args
hbreak
コマンドと同様であり、
ブレイクポイントも同様に設定されます。
しかし、
tbreak
コマンドの場合と同様、
最初にプログラムがそこで停止した後に、
このブレイクポイントは自動的に削除されます。
また、
hbreak
コマンドの場合と同様、
このブレイクポイントはハードウェアの持つ機能を利用するものであり、
ターゲット・ハードウェアによっては、
そのような機能がないこともあるでしょう。
ブレイクポイントの無効化を参照してください。
それから、
ブレイクポイントの成立条件を参照してください。
rbreak regex
break
コマンドで設定されたブレイクポイントと同様に扱われます。
他のすべてのブレイクポイントと同様の方法で、
削除、
無効化、
条件の設定が可能です。
C++プログラムをデバッグする際に、
任意の特別なクラスのメンバではないオーバロードされた関数にブレイクポイントを設定するのに、
rbreak
コマンドは便利です。
info breakpoints [n]
info break [n]
info watchpoints [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
breakpoint
watchpoint
longjmp
longjmp
が呼び出されたときに正しくステップ処理ができるよう内部的に設定されたブレイクポイント
longjmp resume
longjmp
のターゲットとなる箇所に内部的に設定されたブレイクポイント
until
until
コマンドで一時的に使用される内部的なブレイクポイント
finish
finish
コマンドで一時的に使用される内部的なブレイクポイント
ウォッチポイントを設定することで、 ある式の値が変化したときに、 その値の変更がプログラムのどの部分で起るかをあらかじめ知ることなく、 プログラムの実行を停止させることができます。 現在のところ、 ウォッチポイントは他のブレイクポイントと比較して2倍以上の時間がかかります。 それでも、 プログラムのどの部分が問題を発生させたのか全く手掛りのない誤りを検出できるのは、 十分価値のあることです。
watch expr
watch
コマンドを支援してくれます。
しかし、
ハードウェアのブレイクポイント・レジスタはデータに対するウォッチポイントを2つまでしか持てませんし、
2つのウォッチポイントは同一タイプでなければなりません。
例えば、
watch
コマンドによる2つのウォッチポイントの設定、
rwatch
コマンドによる2つのウォッチポイントの設定、
awatch
コマンドによる2つのウオッチポイントの設定はいずれも可能です。
しかし、
2つのウォッチポイントを異なるコマンドで設定することはできません。
2つのタイプのウォッチポイントを混在させようとすると、
GDBにより拒絶されます。
新たにウォッチポイントを設定する際には、
不要なウォッチポイントを削除もしくは無効化してください。
rwatch expr
rwatch
コマンドで設定されていなければなりません。
awatch expr
awatch
コマンドで設定されていなければなりません。
info watchpoints
info break
と同様のコマンドです。
注意: マルチスレッド・プログラムでは、 ウォッチポイントの有用性は限定されます。 現在のウォッチポイントの実装では、 GDBは単一スレッド内部でしか式の値を監視することができません。 式の値が、 カレント・スレッドの処理によってのみ変更されることが確実であれば (そして、 他のスレッドがカレントにならないことが確実であれば)、 ウォッチポイントを通常どおり使用することができます。 しかし、 カレント・スレッド以外のスレッドが式の値を変更させると、 GDBはその変更に気がつかないかもしれません。
GNU C++などの言語は、 例外処理を実装しています。 GDBを使用することで、 どのような原因でユーザ・プログラムが例外を発生させたのかを調べたり、 ある一時点においてユーザ・プログラムが処理することのできる例外の一覧を表示させたりすることができます。
catch exceptions
catch
コマンドを使用することで、
アクティブな例外ハンドラにブレイクポイントを設定することができます。
exceptionsには、
キャッチすべき例外の名前の一覧を指定します。
info catch
コマンドにより、
アクティブな例外ハンドラの一覧を表示することができます。
フレームに関する情報を参照してください。
現在、
GDBの例外処理にはいくつかの制限があります。
例外処理をデバッグするのに、
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
clear linenum
clear filename:linenum
delete [breakpoints] [bnums...]
set confirm off
コマンドが事前に実行されていない場合、
GDBは、
削除してもよいかどうか確認を求めてきます)。
このコマンドの省略形は
d
です。
ブレイクポイントやウォッチポイントを削除するのではなく、
無効化したい場合もあるでしょう。
これは、
ブレイクポイントを、
それがあたかも削除されたかのように機能しなくしてしまいますが、
後に再度有効にすることができるよう、
そのブレイクポイントに関する情報を記憶します。
ブレイクポイントおよびウォッチポイントは、
enable
とdisable
コマンドによって有効化、
無効化します。
これらのコマンドには、
引数として1つ以上のブレイクポイント番号を指定することも可能です。
指定すべき番号がわからない場合は、
info break
コマンドもしくはinfo watch
コマンドによってブレイクポイント、
ウォッチポイントの一覧を表示してください。
ブレイクポイント、
ウォッチポイントは、
有効/無効という観点からは4つの異なる状態を持つことができます。
break
コマンドで設定されたブレイクポイントの初期状態はこの状態です。
tbreak
コマンドで設定されたブレイクポイントの初期状態はこの状態です。
以下のコマンドを使用することで、 ブレイクポイントおよびウォッチポイントの有効化、 無効化が可能です。
disable [breakpoints] [bnums...]
disable
コマンドは
dis
と省略することができます。
enable [breakpoints] [bnums...]
enable [breakpoints] once bnums...
enable [breakpoints] delete bnums...
tbreak
コマンド
(ブレイクポイントの設定を参照)
で設定されたブレイクポイントを除き、
ユーザによって設定されたブレイクポイントの初期状態は有効状態です。
その後、
ユーザが上記のコマンドのいずれかを使用した場合に限り、
無効化されたり有効化されたりします
(until
コマンドは、
それ自身でブレイクポイントを設定し削除することができますが、
ユーザの設定した他のブレイクポイントの状態は変更しません。
継続実行とステップ実行を参照)。
最も単純なブレイクポイントは、
指定された箇所にプログラムが到達するたびに、
プログラムの実行を停止させます。
ブレイクポイントに対して条件を指定することも可能です。
ここで、
「条件」とは、
プログラムが記述された言語において真偽値を表す式のことです
(式を参照)。
条件付きのブレイクポイントにプログラムが到達するたびに、
その式が評価されます。
そして、
その結果が真であった場合だけ、プログラムは停止します。
これは、
プログラムの正当性を検査するために診断式を使用するのとは逆になります。
この場合は、
診断式が成立しないとき、
すなわち条件が偽である場合に、
ユーザはプログラムを停止させます。
C言語では、
assertという診断式をテストするためには、
しかるべきブレイクポイントに`! assert'という条件を設定します。
ウォッチポイントに対して条件を設定することもできます。
もともとウォッチポイントは、
ある式の値を検査するものなのですから、
これは必要ないかもしれません。
しかし、
ある変数の新しい値がある特定の値に等しいか否かを検査するのは条件式に任せて、
ウォッチポイントの対象そのものは単にその変数の名前にするという設定の方が簡単でしょう。
ブレイクポイントの成立条件に副作用を持たせたり、
場合によってはプログラム内部の関数を呼び出させたりすることもできます。
プログラムの進行状況をログに取る関数を呼び出したり、
特別なデータ構造をフォーマットして表示するユーザ定義の関数を使用したい場合などに便利です。
この効果は、
同一アドレスに有効なブレイクポイントが別に設定されていない限り、
完全に予測可能です
(別のブレイクポイントが設定されていると、
GDBはこのブレイクポイントを先に検出し、
他のブレイクポイントで設定した条件式をチェックすることなくプログラムを停止させてしまうかもしれません)。
ただし、
あるブレイクポイントに到達したときに、
副作用を持つ処理を実行させるためには、
ブレイクポイント・コマンドの方がより便利であり、
より柔軟でしょう
(ブレイクポイント・コマンド・リストを参照)。
ブレイクポイントの成立条件は、
ブレイクポイントを設定する際にbreak
コマンドの引数に`if'を使用することで、設定できます。
ブレイクポイントの設定を参照してください。
ブレイクポイントの成立条件は、
condition
コマンドによっていつでも変更できます。
watch
コマンドはif
キーワードを認識しません。
ウォッチポイントに対して条件を追加設定する唯一の方法は、
condition
コマンドを使うことです。
condition bnum expression
condition
コマンドを使用すると、
GDBはただちにexpressionの構文の正当性、
および、
expressionの中で使用されるシンボル参照の、
ブレイクポイントのコンテキストにおける有効性をチェックします。
しかし、
GDBはcondition
コマンドが実行されるときに
expressionの値を実際に評価するわけではありません。
式を参照してください。
condition bnum
ブレイクポイント成立条件の特別なものに、 ブレイクポイントに到達した回数がある数に達したときにプログラムを停止させるというものがあります。 これは大変便利なので、 それを実現するための特別な方法が提供されています。 それは、 ブレイクポイントの通過カウント (ignore count) を使用する方法です。 すべてのブレイクポイントは、 通過カウントと呼ばれる整数値を持っています。 ほとんどの場合、 この通過カウントの値はゼロであり、 何ら影響力を持ちません。 しかし、 通過カウントとして正の値を持つブレイクポイントに到達すると、 ユーザ・プログラムはそこで停止せず、 単に通過カウントの値を1減少させて処理を継続します。 したがって、 通過カウントがnであると、 ユーザ・プログラムがそのブレイクポイントに到達した回数がn以下の間は、 そのブレイクポイントにおいてプログラムは停止しません。
ignore bnum count
continue
コマンドを使用して実行を再開する場合、
ignore
コマンドを使用することなく、
直接continue
コマンドの引数に通過カウントを指定することができます。
継続実行とステップ実行を参照してください。
ブレイクポイントが通過カウントとして正の値を持ち、
かつ、
成立条件を持つ場合、
成立条件はチェックされません。
通過カウントが0に達すると、
GDBは成立条件のチェックを再開します。
`$foo-- <= 0'のように、
評価のたびに値の減少するデバッガのコンビニエンス変数を使用した評価式によって、
通過カウントと同様の効果を達成することができます。
コンビニエンス変数を参照してください。
ブレイクポイント (もしくはウォッチポイント) に対して、 それによってプログラムが停止したときに実行される一連のコマンドを指定することができます。 例えば、 ある特定の式の値を表示したり、 他のブレイクポイントを有効化したりできると便利なこともあるでしょう。
commands [bnum]
... command-list ...
end
end
だけから成る1行を記述します。
ブレイクポイントからすべてのコマンドを削除するには、
commands
行に続いて
(コマンドを1つも指定せずに)
end
を記述します。
引数bnumが指定されない場合、
commands
は最後に設定されたブレイクポイントもしくはウォッチポイントを対象とします
(最後に到達したブレイクポイントではありません)。
command-listの記述中は、
RETキーが持つ、
最後に実行されたコマンドを繰り返し実行する機能は無効です。
ブレイクポイント・コマンドを使用してプログラムの実行を再開することができます。
continue
、
step
、
あるいは実行を再開させるその他のコマンドを使用してください。
コマンド・リストの中で、
実行を再開するコマンドの後に記述されているものは無視されます。
というのは、
プログラムが実行を再開すると
(たとえそれがnext
コマンドやstep
コマンドによるものであっても)
別のブレイクポイントに到達する可能性があり、
そのブレイクポイントがコマンド・リストを持っていると、
どちらのリストを実行するべきかあいまいになるからです。
コマンド・リストの先頭に指定されたコマンドがsilent
であると、
ブレイクポイントで停止したときに通常出力されるメッセージは表示されません。
これは、
ある特定のメッセージを出力するだけで実行を継続するようなブレイクポイントを設定するのに望ましいでしょう。
コマンド・リスト中の後続のコマンドがどれもメッセージを出力しない場合、
ブレイクポイントに到達したことをユーザに示すものは何もないことになります。
silent
はブレイクポイント・コマンド・リストの先頭においてのみ意味を持ちます。
echo
、
output
、
printf
の各コマンドを使用することで、
細かく管理された出力を表示することができます。
これらのコマンドは、
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)
継続実行とは、
ユーザ・プログラムの実行を再開して、
それが正常に終了するまで実行させることを指します。
一方、
ステップ実行とは、
ユーザ・プログラムを1「ステップ」だけ実行することを指します。
ここで「ステップ」とは、
(使用されるコマンドによって)
ソース・コード1行を指すこともありますし、
1マシン命令を指すこともあります。
継続実行の場合でもステップ実行の場合でも、
ブレイクポイントやシグナル
のためにユーザ・プログラムが正常終了する前に停止することがあります
(シグナルによってプログラムが停止した場合、
実行を再開するには
handle
コマンドもしくは`signal 0'
コマンドを使用するとよいでしょう。
シグナルを参照してください)
。
continue [ignore-count]
c [ignore-count]
fg [ignore-count]
ignore
コマンドと似た効果を持ちます
(ブレイクポイントの成立条件を参照)。
引数ignore-countは、
ユーザ・プログラムがブレイクポイントによって停止した場合にのみ意味を持ちます。
これ以外の場合には、
continue
コマンドへの引数は無視されます。
c
およびfg
は、
簡便さのためだけに提供されている同義コマンドで、
continue
コマンドと全く同様の動作をします。
別の箇所で実行を再開するには、
呼び出し関数に戻るreturn
コマンド
(関数からの復帰を参照)、
もしくは、
ユーザ・プログラム内の任意の箇所へ移動するためのjump
コマンド
(異なるアドレスにおける処理継続を参照)
を使用することができます。
ステップ実行の典型的な使用方法は、
問題があると思われる関数あるいはプログラム部分の先頭にブレイクポイントを設定
(ブレイクポイント、ウォッチポイント、例外を参照)
し、
ブレイクポイントで停止するまでプログラムを実行させた後、
問題が再現するまで、
関連しそうな変数の値を調べながら疑わしい部分を1行ずつ実行することです。
step
s
です。
現在、注意: デバッグ情報なしでコンパイルされた関数の内部にいるときに
step
コマンドを使用すると、 デバッグ情報付きの関数に達するまでプログラムの実行は継続されます。 同様に、step
コマンドはデバッグ情報なしでコンパイルされた関数の内部へ入って、 停止することはありません。 デバッグ情報を持たない関数の内部でステップ実行を行うには、 後述のstepi
コマンドを使用してください。
step
コマンドは、
ソース・コード行の最初の命令においてのみ停止します。
これにより、
以前のバージョンで発生した、
switch
文やfor
文などにおいて複数回停止してしまうという問題が回避されています。
行の中にデバッグ情報を持つ関数への呼び出しがあると、
step
コマンドは続けて停止します。
さらに、現在のstep
コマンドは、
サブルーチンが行番号情報を持つ場合に限り、
サブルーチンの内部に入り込みます。
サブルーチンが行番号情報を持たない場合、
step
コマンドはnext
コマンドと同様の動作をします。
これにより、
MIPSマシン上でcc -gl
を使用した場合に発生していた問題が回避されています。
以前のバージョンでは、
サブルーチンが何らかのデバッグ情報を持っていれば、
その内部に入り込んでいました。
step count
step
コマンドによるステップ実行をcount回繰り返します。
ステップ実行をcount回繰り返し終わる前に、
ブレイクポイントに到達する
か、
もしくは、
ステップ実行とは関連のないシグナルが発生した
場合には、
ただちにステップ実行を中断して停止します。
next [count]
step
コマンドと似ていますが、
next
コマンドは、
ソース・コード上に関数呼び出しが存在すると、
その関数を停止することなく最後まで実行します。
プログラムが停止するのは、
next
コマンドを実行したときと同一のスタック・フレーム上において、
ソース・コード上異なる行まで実行が継続されたときです。
このコマンドの省略形はn
です。
引数countは、
step
コマンドの場合と同様、
繰り返し回数です。
現在next
コマンドは、
ソース・コード行の最初の命令においてのみ停止します。
これにより、
以前のバージョンで発生した、
switch
文やfor
文などにおいて複数回停止してしまうという問題が回避されています。
finish
return
コマンド
(関数からの復帰を参照)
とこれを比較してみてください。
u
until
next
コマンドに似ていますが、
唯一の相違点は、
until
コマンドによる実行中にジャンプ命令が実行された場合、
プログラム・カウンタの値がジャンプ命令のアドレスより大きくなるまで、
プログラムが継続実行されるという点です。
これは、
ステップ実行によってループ内の最後の行に到達した後にuntil
コマンドを実行することで、
ループから抜け出るまでプログラムを継続実行させることができるということを意味しています。
これに対して、
ループ内の最後の行でnext
コマンドを実行すると、
プログラムはループの先頭に戻ってしまうので、
ループ内の処理を繰り返すことを余儀なくされます。
until
コマンドの実行により、
プログラムがカレントなスタック・フレームから抜け出ようとすると、
そこでuntil
コマンドはプログラムを停止します。
実行されるマシン・コードの順序がソース行の順序と一致しない場合、
until
コマンドは直観にいくらか反するような結果をもたらすかもしれません。
例えば、
以下に挙げるデバッグ・セッションからの抜粋では、
f
(frame
)
コマンドによって、
プログラムが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
break
コマンドの受け付ける形式の引数です
(ブレイクポイントの設定を参照)。
この形式によるbreak
コマンドはブレイクポイントを使用するため、
引数のないuntil
コマンドより処理性能が優れています。
stepi
si
step
コマンドと同様、
繰り返し回数を取ります。
nexti
ni
next
コマンドと同様、
繰り返し回数を取ります。
シグナルは、
プログラム内で発生する非同期イベントです。
オペレーティング・システムが、
使用可能なシグナルの種類を定義し、
それぞれに名前と番号を割り当てます。
例えば、
UNIXにおいては、
割り込み
(通常は、Ctrlキーを押しながらCを押す)
を入力したときにプログラムが受信する
SIGINT
、
その使用領域からかけ離れたメモリ域を参照したときにプログラムが受信するSIGSEGV
、
アラームのタイムアウト時に発生する
(プログラムからアラームを要求した場合にのみ発生する)
SIGALRM
シグナルなどがあります。
SIGALRM
など、
いくつかのシグナルは、
プログラムの正常な機能の一部です。
SIGSEGV
などの他のシグナルは、
エラーを意味します。
これらのシグナルは、
プログラムが事前にそれを処理する何らかの方法を指定しないと、
致命的な
(プログラムを即座に終了させる)
ものとなります。
SIGINT
はユーザ・プログラム内部のエラーを意味するものではありませんが、
通常は致命的なものであり、
よって割り込みの目的であるプログラムの終了を実現することができます。
GDBは、
ユーザ・プログラム内部における任意のシグナル発生を検出することができます。
ユーザは、
個々のシグナルの発生時に何を実行するかを、
GDBに対して事前に指定することができます。
通常GDBは、
SIGALRM
のようなエラーではないシグナルを無視するよう
(これらのシグナルがユーザ・プログラムの中で持っている役割を妨害することのないよう)
設定されています。
その一方で、
エラーのシグナルが発生した場合にはすぐにユーザ・プログラムを停止させるよう設定されています。
これらの設定はhandle
コマンドによって変更することができます。
info signals
info handle
はinfo signals
に対して設定された新しい別名です。
handle signal keywords...
handle
コマンドが受け付けるキーワードには省略形を使用することができます。
省略しない場合、
キーワードは以下のようになります。
nostop
stop
print
キーワードを暗黙のうちに含みます。
print
noprint
nostop
キーワードを暗黙のうちに含みます。
pass
nopass
シグナルによってユーザ・プログラムが停止するとき、
そのシグナルは実行を継続するまで認識できません。
その時点において、
そのシグナルに対してpass
キーワードが有効であれば、
ユーザ・プログラムは実行継続時にシグナルを検出します。
言い換えれば、
GDBがシグナルの発生を報告してきたとき、
handle
コマンドでpass
もしくはnopass
を使用することで、
実行を継続したときにプログラムにそのシグナルを検出させるか否かを管理することができます。
またsignal
コマンドを使用することによって、
ユーザ・プログラムがシグナルを検出できないようにしたり、
通常は検出できないシグナルを検出できるようにしたり、
あるいは任意の時点で任意のシグナルをユーザ・プログラムに検出させたりすることができます。
例えば、
ユーザ・プログラムが何らかのメモリ参照エラーによって停止した場合、
ユーザは、
さらに実行を継続しようとして、
問題のある変数に正しい値を設定して継続実行しようとするかもしれません。
しかし、
実行継続直後に検出される致命的なシグナルのために、
おそらくユーザ・プログラムはすぐに終了してしまうでしょう。
このようなことを回避したければ、
`signal 0'コマンドによって実行を継続することができます。
ユーザ・プログラムへのシグナルの通知を参照してください。
ユーザ・プログラムが複数のスレッドを持つ場合 (マルチスレッド・プログラムのデバッグを参照)、 すべてのスレッドにブレイクポイントを設定するか、 特定のスレッドにブレイクポイントを設定するかを選択することができます。
break linespec thread threadno
break linespec thread threadno if ...
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つの文の間の境界のところでぴったり停止するよりも、
文の途中で停止してしまう方が一般的です。
また、
継続実行やステップ実行の結果、
プログラムが別のスレッド内で停止してしまうこともありえます。
継続実行あるいはステップ実行されたスレッドがユーザの要求した処理を完了する前に、
他のスレッドがブレイクポイントに到達した場合、
シグナルを受信した場合、
例外が発生した場合などに、
このようなことが発生します。