dbx コマンドによるデバッグ

第 4 章 プログラムの実行制御

実行、ステップ、および続行に使用されるコマンド (runrerunnextstep、および cont) は、プロセス制御コマンドと呼ばれます。

このマニュアルで後述するイベント管理コマンドとともに使用すると、プログラムが dbx のもとで実行されるときに、その実行時の動作を管理できます。

この章では、dbx におけるプログラムの実行、接続、継続、および再実行の方法と、プログラムコードの各行をステップ実行する方法を説明します。

この章は次の各節から構成されています。

dbx でプログラムを実行する

プログラムを初めて dbx に読み込むと、dbx はそのプログラムの「メイン」ブロック (C, C++, Fortran 90 の場合は main()、FORTRAN 77 の場合は MAIN) におとずれます。dbx は続いて、ユーザーから出されるコマンドを待機します。ここで、別の部分のコードを表示したり、イベント管理コマンドを使用したりすることができます。

プログラムを実行する前に、そのプログラムにブレークポイントを設定することもできます。準備ができたら、run コマンドを使用してプログラムを実行してください。

dbx で引数を指定しないでプログラムを実行するには、次のように入力します。


(dbx) run

任意でコマンド行の引数と入出力の切り替えを追加できます。この場合は、次のように入力します。


(dbx) run [arguments ][ < input_file]  [ > output_file]

run コマンドの出力は、dbx を実行しているシェルに noclobber を設定した場合でも、既存ファイルを上書きします。

run コマンドそのものは、前の引数とリダイレクトを使用して、プログラムを実行します。rerun コマンドは、元の引数とリダイレクトなしでプログラムを実行します。

動作中のプロセスに dbx を接続する

すでに動作中のプログラムをデバッグしなければならないことがあります。動作中のプロセスにデバッグ機能を接続しなければならないのは、次のような場合です。

このような場合は、動作中のプログラムの プロセス ID (pid) を引数として dbx コマンドに渡せば、そのプログラムに dbx を接続することができます。

デバッグを終了すると、detach コマンドが使用され、プロセスを終了することなく dbx の制御からプログラムを解放することができます。

動作中のプロセスに接続されているときに dbx を終了すると、dbx は終了前に自動的な切り離しを行います。

dbx から独立して動作しているプログラムに dbx を接続するには、次のようにします。

  1. dbx がすでに起動され、動作している場合は、次のように入力します。


    (dbx) debug program_name process_ID
    

    プログラム名 program_name はハイフン "-" で省略することができます。dbx はプロセス ID が process_ID に対応するプログラムを自動的に見つけて読み込みます。

  2. dbx が動作していない場合は、プロセス ID (pid) を引数にして dbx を起動します。


    % dbx program_name process_ID
    

    プログラムに dbx を接続すると、そのプログラムは実行を停止します。このプログラムは、dbx に読み込んだプログラムの場合と同様にして調べることができます。任意のイベント管理コマンドまたはプロセス制御コマンドを使用してデバッグできます。

プロセスから dbx を切り離す

プログラムのデバッグが終了したら、detach コマンドを使用して dbx をプログラムから切り離してください。プログラムは dbx から独立して動作を再開します。

dbx の制御下から動作中のプロセスを切り離すには、次のように入力します。


 
(dbx) detach

プログラムの実行

dbx は、nextstep というステップ実行のための基本コマンドに加え、ステップの変形である step up をサポートします。next step はともに、プログラムにソースの 1 行を実行させ、停止します。

実行された行に関数呼び出しが含まれている場合、next はその関数を実行し、呼び出し側に戻ります。step は呼び出された関数の先頭の行で停止します。

step up は、被呼び出し側関数から呼び出し側関数に制御を戻します。

ステップ実行する行数を指定できます。dbx コマンド stepnext は、一度に実行するソースコードの行数を指定する引数を受け付けます。この引数のデフォルト値は 1 です。

ソースコードをある行数だけステップ実行するには、next または step のどちらか適切な dbx コマンドの後ろに、1 度に実行したい行数 n を指定します。


(dbx) step n

pop はスタックの一番上のフレームをポップし、それに応じてフレームポインタとスタックポインタを調整します。また pop コマンドは、プログラムカウンタをソース行の先頭に変更します。

関数を呼び出す

プログラムが停止しているとき、dbx コマンド call を使用して関数を呼び出すことができます。call コマンドには、被呼び出し側関数に渡す必要のあるパラメータの値を指定することもできます。

関数 (手続き) を呼び出すには、 関数の名前を入力し、その引数を指定します。たとえば、次のように入力します。


(dbx) call change_glyph(1,3)

引数 parameters は省略できますが、関数名 function_name の後には必ず括弧を入力してください。たとえば、次のように入力します。


(dbx) call type_vehicle()

関数が定義されているソースファイルが -g フラグでコンパイルされたものであるか、プロトタイプ宣言が現在のスコープで可視であれば、dbx は引数の数と型をチェックし、不一致があったときはエラーメッセージを出します。それ以外の場合、dbx は引数の数をチェックしません。

デフォルトでは、call コマンドが実行されるたびに、dbxfflush(stdout) を自動的に呼び出し、入出力バッファに格納されているすべての情報を出力します。この関数は、 call コマンドを使用して明示的に呼び出したり、関数呼び出しを含む式を評価するか、条件つき修飾語 (“stop in glyph -if animate()” など) を使用することにより暗示的に呼び出すことができます。自動的なフラッシュをオフにするには、dbxenv output_autoflush を off に設定してください。

C++ の場合、dbx はデフォルト引数と関数の多重定義も処理します。可能であれば、C++ 多重定義関数の自動解析が行われます。関数を特定できない場合は (関数が -g でコンパイルされていない場合など)、多重定義名のリストが表示されます。

call を使用すると、dbxnext のように動作し、被呼び出し側から戻ります。しかし、プログラムが被呼び出し側関数でブレークポイントにあたると、dbx はそのブレークポイントでプログラムを停止し、メッセージを表示します。ここで where コマンドを実行すると、dbx コマンドのレベルを起点として呼び出しが行われたことが示されます。

実行を継続すると、呼び出しは正常に戻ります。強制終了、実行、再実行、デバッグを行おうとすると、dbx は入れ子になったインタプリタから回復しようとするので、コマンドが異常終了します。異常終了したコマンドは再発行することができます。また、pop -c コマンドを使用して、すべてのフレームを最後の呼び出しまでポップ (解放) することもできます。

プログラムを継続する

プログラムを継続するには、cont コマンドを使用します。


(dbx) cont

cont コマンドには、派生関数の cont at line_number があります。これを使用すると、現在のプログラム位置の行以外の行を指定して、プログラムの実行を再開することができます。これにより、再コンパイルすることなく、問題を起こすことがわかっている 1 行または複数行のコードをスキップできます。

特定の行からプログラムを継続するには、cont at line_number コマンドを入力します。たとえば、次のように入力します。


(dbx) cont at 124

行番号は、プログラムが停止しているファイルから計算される点に注意してください。指定した行番号は、関数のスコープ内になければなりません。

cont at の有効な応用例として、assign コマンドとともに使用する方法があります。cont at line-number (行番号) と assign とを組み合わせると、ある変数の値を正しく計算できない関数の呼び出しが含まれている行を実行しないようにすることが可能です。

特定の行からプログラムの実行を再開するには、次のようにします。

  1. assign を使用して変数に正しい値を代入します。

  2. cont at line-number で、その値を正しく計算できない関数の呼び出しが含まれている行を飛ばします。

プログラムが 123 行目で停止しているものとします。その行では、関数 how_fast() を呼び出しています。この関数は、変数 speed を正しく計算しません。speed の正しい値がわかっているため、speed に値を代入することができます。その後、how_fast() の呼び出しを飛ばして、プログラムの実行を 124 行目から継続します。


(dbx) assign speed = 180; cont at 124;

このコマンドを when ブレークポイントコマンドとともに使用すると、プログラムは 123 行目の実行を試みるたびに how_fast() の呼び出しを飛ばします。


 

(dbx) when at 123 { assign speed = 180; cont at 124;}

Control+C によってプロセスを停止する

dbx で実行中のプロセスは、Control +C (^C) を使用して停止できます。^C によってプロセスを停止すると、dbx^C を無視しますが、子プロセスはそれを SIGINT と見なして停止します。このプロセスは、それがブレークポイントによって停止しているときと同じように検査することができます。

^C によってプログラムを停止した後に実行を再開するには、コマンド cont を使用します。実行を再開する場合、cont に修飾語 sig <シグナル名> は必要ありません。cont コマンドは、保留シグナルをキャンセルした後で子プロセスを再開します。

コマンド参照

run

現在の引数でプログラムを実行するには、run コマンドを単独で使用します。


run

新しい引数を使用してプログラムの実行を開始するには、次のように入力します。


run args

rerun

引数を付けないでプログラムを再実行するには、次のように入力します。


rerun

next

引数を付けないで next コマンドを実行すると、1 行実行します。実行する行が関数の場合は、その関数をすべて実行します。


next

n 行実行するには、次のように入力します。


next n

next コマンドの実行中に指定のシグナルを配信するには、次のように入力します。


next ... -sig sig

dbxenv 変数の step_events は、ステップ中にブレークポイントが有効になるかどうかを指定します。

指定スレッドをステップ実行するには、次のように入力します。


next tid

指定 LWP をステップ実行するには、次のように入力します。


next lwpid

これは、関数をとばすときに、すべての LWP を暗黙で再開するものではありません。明示的な tid または lwpid が指定されている場合、総称 next のデッドロック回避手段は無効になります。

マルチスレッドプログラムでは、関数呼び出しに移動すると、その関数の実行中すべての LWP が暗黙指定で開始されて、デッドロックを回避します。非活動状態のスレッドをとばすことはできません。

cont

cont コマンドは、実行を続ける場合に使用します。マルチスレッドプロセスでは、すべてのスレッドが再開されます。


cont

lineid で指定された行で実行を続けるには、次のように入力します。lineid は任意指定です。


cont lineid

signo で指定されたシグナルで実行を続けるには、次のように入力します。


cont ... -sig signo

特定のスレッドまたは LWP から実行を続けるには、次のように入力します。


cont ... id

実行を続けて、フォークされたプロセスの後を追うには、次のように入力します。


cont ... -follow parent|child

step

step コマンドに引数を付けずに実行すると、1 行ステップ実行します。


step

n 行ステップ実行するには、次のように入力します。


step n

n 行ステップ実行して、現在の関数から出るには、次のように入力します。


step up n

step コマンドの実行中に指定のシグナルを配信するには、次のように入力します。


step ... -sig sig

dbxenv 変数 step_events は、ブレークポイントがステップ中に有効になるかどうかを指定します。

指定のスレッドをステップ実行するには、次のように入力します (step up は適用されません)。


step ... tid

指定の LWP をステップ実行するには、次のように入力します。


step ... lwpid

これにより、関数をステップ実行するときにすべての LWP が暗黙で再開されることはありません。明示的な tid または lwpid が指定されている場合、総称 step のデッドロック回避手段は無効になります。

マルチスレッドプログラムでは、関数呼び出しに移動すると、その関数呼び出しの間中、すべての LWP が暗黙で再開されて、デッドロックを回避します。非活動状態のスレッドのステップ実行はできません。

debug

debug コマンドは、デバッグ中のプログラムの名前と引数を出力します。


debug

プロセスまたはコアを指定しないでプログラムのデバッグを開始するには、次のように入力します。


debug program

コアファイル core を持つプログラムのデバッグを開始するには、次のように入力します。


debug -c core program
または
debug program core

プロセス ID pid を持つプログラムのデバッグを開始するには、次のように入力します。


debug -p pid program
または
debug program pid

コアファイルが一致しない場合でも、その読み込みを強制的に実行するには、次のように入力します。


debug -f ...

すべての displaytracewhen、および stop コマンドを保存するには、次のように入力します。-r オプションが指定されていない場合は、delete allundisplay 0 が実行されます。


debug -r

プログラム名 がダッシュで始まる場合でもプログラムのデバッグを開始するには、次のように入力します。


debug [options] -- program

detach

detach コマンドは、dbx をターゲットから切り離して、保留中のシグナルすべてをキャンセルします。


detach

指定のシグナルの転送中に切り離すには、次にように入力します。


detach -sig sig