| dbx コマンドによるデバッグ |      | 
第 5 章
ブレークポイントとトレースの設定
ブレークポイントは、アクションが発生する場所であり、そのポイントでプログラムは実行を停止します。トレースを設定することにより、変数の値の変更など、プログラムでのイベントに関する情報を表示することができます。トレースの動作は、ブレークポイントの動作とは異なりますが、トレースとブレークポイントは同様のイベントハンドラを共有します。
この章では、ブレークポイントとトレースの設定方法とウォッチポイントの使用方法について説明します。
ブレークポイントを設定する
dbxでは、ソースレベルのブレークポイントを設定するため、3 種類のブレークポイントアクションコマンドを使用することができます。
stopブレークポイント -stopコマンドによって作成されたブレークポイントに到達すると、プログラムは停止します。停止したプログラムはほかのdbxコマンドを実行するまで再開されません。
whenブレークポイント - プログラムは停止し、dbxが 1 つまたは複数のdbxコマンドを実行した後、プログラムは再開します。プログラムは、コマンドの中にstopが含まれていない限り処理を続けます。
traceブレークポイント - プログラムは停止し、イベント固有のトレース情報行を出力した後、プログラムは再開します。マシンレベルのブレークポイントを設定するには、
stopi、wheni、traceiコマンドを使用します (第 17 章を参照)。ソースコードの特定の行に
stopブレークポイントを設定する
dbx stop atコマンドを使用して、行番号にブレークポイントを設定します。ここで、n はソースコードの行番号、filename は任意のプログラムファイル名修飾子です。
(dbx)stop atfilename:nここで、n はソースコードの行番号、filename はそのコードが含まれているソースファイルの名前 (省略可能) です。たとえば、次のようにします。
(dbx)stop at main.cc:3
stopまたはwhenコマンドに指定された行が、ソースコードの実行可能行ではない場合、dbxは次の有効な実行可能行にブレークポイントを設定します。実行可能な行がない場合、dbxはエラーを出します。「ブレークポイント」ウィンドウ内でもブレークポイントを設定できます。詳細については、Sun WorkShop オンラインヘルプの「デバッグウィンドウの使い方」の「ブレークポイント (行に設定)」を参照してください。
関数に
stopブレークポイントを設定する
dbx stop inコマンドを使用して、関数にブレークポイントを設定します。
(dbx)stop infunction指定関数中で停止するブレークポイントは、プロシージャまたは関数の最初のソース行の冒頭でプログラムの実行を中断します。
「デバッグ」ウィンドウで、関数にブレークポイントを設定することもできます。詳細については、Sun WorkShop オンラインヘルプの「デバッグウィンドウの使い方」の「ブレークポイント (関数に設定)」を参照してください。
dbx は、以下の場合を除いては、ユーザーが参照している変数または関数を決定します。
グローバル関数
foo(int)にブレークポイントを設定します。メンバー関数にブレークポイントを設定するには、次のコマンドを使用します。
dbxは、ユーザーがグローバル関数foo(int)、グローバル関数foo(double)のどちらを意味しているのかを判断することができず、明確にするため、オーバーロードしたメニューを表示する場合があります。
dbxは、ユーザーがグローバル関数bar()、メンバー関数bar()のどちらを意味しているのかを判断することができないため、オーバーロードしたメニューを表示します。
特定の行にwhenタイプのブレークポイントを設定する
whenタイプのブレークポイントは、ほかのdbxコマンドを副作用コマンドとして利用できます。たとえば、whenでlistコマンドを副作用コマンドとして用いれば、独自のトレースを実現することができます。
(dbx)when at 123 { list $lineno;}
whenはcontコマンドを暗黙指定して動作します。上の例の場合、現在行のコードを出力した後、プログラムの実行が続けられます。動的にリンクされたライブラリにブレークポイントを設定する
実行時リンカーとの間でプログラムインタフェースを使用するコード、すなわち
dlopen()、dlclose()、およびそれらに関連する関数を呼び出すコードをデバッグするときは、dbxの全機能を利用できます。実行時リンカーは、プログラムの実行中に共有ライブラリをリンクしたり、そのリンクを解除したりします。dlopen()と
dlclose()のサポートにより、動的にリンクされている共有ライブラリの関数もプログラムの起動時にリンクされたライブラリの関数と同様に、ステップ実行したり、ブレークポイントを設定したりできます。
dlopen()によって読み込まれるライブラリには、そのライブラリがdlopen()によって読み込まれる前にブレークポイントを設定することはできません。
dlopen()によって読み込まれたフィルタライブラリには、その中の最初の関数が呼び出されるまでブレークポイントを設定することはできません。- ライブラリが
dlopen()によって読み込まれるとき、_init()という名前の初期化ルーチンが呼び出されます。このルーチンは、ライブラリ内のほかのルーチンを呼び出すことがあります。この初期化が終わるまで、dbxは読み込まれたライブラリにブレークポイントを置くことができません。dlopen()によって読み込まれたライブラリの_init()内でdbxを停止させることはできません。C++ プログラムに複数のブレークポイントを設定する
異なるクラスのメンバー関数の呼び出し、特定のクラスのすべてのメンバー関数の呼び出し、または多重定義されたトップレベル関数の呼び出しに関連する問題が発生する可能性があります。このような場合に対処するために、
inmember、inclass、infunctionまたはinobjectのキーワードのうちの 1 つをstop,when,またはtraceコマンドとともに使用することにより、1 回のコマンドで C++ コードに複数のブレークポイントを挿入できます。異なるクラスのメンバー関数にブレークポイントを設定する
特定のメンバー関数のオブジェクト固有のもの (同じメンバー関数名でクラスの異なるもの) それぞれにブレークポイントを設定するには、stop inmemberを使用します。
whenブレークポイントを設定するには、whenコマンドをキーワードinmemberとともに使用します。たとえば、関数
drawが複数の異なるクラスに定義されている場合は、それぞれの関数ごとにブレークポイントを設定します。
stop inmember draw「ブレークポイント」ウィンドウで、「指定メンバー中で」ブレークポイントを設定することもできます。詳細については、Sun WorkShop オンラインヘルプの「デバッグウィンドウの使い方」の「指定メンバー中でブレークポイントの設定」を参照してください。
同じクラスのメンバー関数にブレークポイントを設定する
特定のクラスのすべてのメンバー関数にブレークポイントを設定するには、stopinclassコマンドを使用します。
whenタイプのブレークポイントを設定する場合は、whenコマンドをキーワードinclassとともに使用します。クラス wedge のすべてのメンバー関数にブレークポイントを設定するには、次のように入力します。
(dbx)stop inclass wedge「ブレークポイント」ウィンドウで、「指定クラスの中で」ブレークポイントを設定することもできます。詳細については、Sun WorkShop オンラインヘルプの「デバッグウィンドウの使い方」の「指定クラスの中でプレークポイントの設定」を参照してください。
ブレークポイントは、該当するクラスで定義されているクラスメンバー関数にだけ挿入されます。基底クラスから継承された関数には挿入されません。
stop inclassおよびその他のブレークポイントを選択することにより、大量のブレークポイントが挿入される場合があるため、dbx環境変数step_eventsを必ずonに設定し、stepおよびnextコマンドの実行速度を上げるようにしてください (「イベント効率」参照)。非メンバー関数に複数のブレークポイントを設定する
多重定義された名前を持つ非メンバー関数 (同じ名前を持ち、引数の型または数の異なるもの) に複数のブレークポイントを設定するには、
stop infunctionコマンドを使用します。
whenタイプのブレークポイントを設定する場合は、whenコマンドをキーワードinfunctionとともに使用します。たとえば、C++ プログラムで
sort()という名前の関数が 2 種類定義されていて、一方がint型の引数、もう一方がfloat型の引数をとる場合に、両方の関数にブレークポイントを置くためには、次のように入力します。
(dbx)when infunction sort {cmd;}「ブレークポイント」ウィンドウで、「指定関数中で」ブレークポイントを設定することもできます。詳細については、Sun WorkShop オンラインヘルプの「デバッグウィンドウの使い方」の「ブレークポイント (関数に設定)」を参照してください。
オブジェクトにブレークポイントを設定する
In Objectブレークポイントを設定して、特定オブジェクトに適用される演算を確認します。In Objectブレークポイントは、オブジェクトから呼び出されると、そのオブジェクトクラスのすべての非静的メンバー関数によるプログラムの実行を中断します。オブジェクト
fooにブレークポイントを設定するには、次のように入力します。
(dbx)stop inobject &foo「ブレークポイント」ウィンドウで、「指定オブジェクト中で」ブレークポイントを設定することもできます。詳細については、Sun WorkShop オンラインヘルプの「デバッグウィンドウの使い方」の「指定オブジェクト中でブレークポイントの設定」を参照してください。
コードをトレースする
トレースは、実行されるコード行、呼び出される関数、変更される変数についての情報を表示します。詳細については、Sun WorkShop オンラインヘルプの「デバッグウィンドウの使い方」の「コードのトレース」を参照してください。
トレースを設定する
コマンド行に
traceコマンドを入力することにより、トレースを設定します。traceコマンドの基本構文は次の通りです。
トレースコマンドの完全な構文については、Sun WorkShop オンラインヘルプの「dbx コマンドの使い方」の「trace コマンド」を参照してください。
「ブレークポイント」ウィンドウで、トレースを設定することもできます。詳細については、Sun WorkShop オンラインヘルプの「デバッグウィンドウの使い方」の「トレースの設定」を参照してください。
トレースで提供される情報は、トレースに関連する event の型に依存します (「イベント指定の設定」を参照)。
トレース速度を制御する
多くのプログラムは高速に実行されるため、表示がよく見えません。環境変数
dbxenv trace_speedを使用して、トレーススコープ内の各行の実行間隔を制御することができます。デフォルトの実行間隔は0.5秒です。トレース時の各行の実行間隔を設定するには、次のように入力します。
「デバッグオプション」ダイアログで、トレースの実行速度を設定することもできます。詳細については、Sun WorkShop オンラインヘルプの「デバッグウィンドウの使い方」の「トレース速度の設定」を参照してください。
イベントハンドラのリストの表示とクリア
dbxセッション中にブレークポイントやトレースポイントを複数設定することがよくあります。dbxには、それらのポイントを表示したりクリアしたりするためのコマンドが用意されています。ブレークポイントとトレースポイントの表示
すべての有効なブレークポイントのリストを表示するには、
statusコマンドを使用します。ブレークポイントは ID 番号付きで表示され、この番号はほかのコマンドで使用できます。C++ の多重ブレークポイントのところでも説明したように、
dbxはキーワードinmember、inclass、infunctionで設定された多重ブレークポイントを、1 つのステータス ID 番号を使用してまとめて報告します。ステータス ID 番号を使用して特定のブレークポイントを削除
statusコマンドを使用してブレークポイントをリスト表示した場合、dbxは、各ブレークポイントの作成時に割り当てられた ID 番号を表示します。deleteコマンドを使用することで、ID 番号によってブレークポイントを削除したり、キーワードallにより、プログラム内のあらゆる場所に現在設定されているブレークポイントをすべて削除することができます。ブレークポイントを ID 番号 ID_number によって削除するには、次のように入力します。
(dbx)delete 3 5
dbxに現在読み込まれているプログラムに設定されているすべてのブレークポイントを削除するには、次のように入力します。
(dbx)delete all詳細については、Sun WorkShop オンラインヘルプの「dbx コマンドの使い方」の「delete コマンド」を参照してください。
ウォッチポイント
ウォッチポイントは、変数または式の値が変化したときにイベントを発生させる
dbxの一般的な機能です。stopコマンドを使用してウォッチポイントを設定することができます。アドレスの内容に書き込みが行われたときに実行を停止する
アドレスの内容に書き込みが行われたときにプログラムの実行を停止するには、次のように入力します。
(dbx)stop modify&variable
- 変数 variable にそれまで設定されていた値と同じ値が書き込まれた場合でもイベントは発生します。
dbxが命令をエミュレートすることによって、メモリーに新しい内容が設定された場合でも、変数への書き込みを行なった命令が実行される前にイベントが発生します。- 関数に局所的な自動変数など、スタック変数のアドレスを使用することはできません。
「ブレークポイント」ウィンドウで、「指定範囲変更時」ブレークポイントを設定することもできます。詳細については、Sun WorkShop オンラインヘルプの「デバッグウィンドウの使い方」の「指定範囲変更時に停止」を参照してください。
指定した変数の値が変化したときに実行を停止する
指定した変数の値が変化したときにプログラムの実行を停止するには、次のように入力します。
(dbx)stop changevariable
dbxは、指定された変数の値に変更があった行の後ろの行でプログラムを停止します。- 変数が関数の局所変数の場合、その関数に最初に制御が移り、変数のための記憶領域が割り当てられた時点で変更があったと見なします。パラメータについても、同じことが言えます。
- 「ブレークポイント」ウィンドウで、「指定変数の値変更時」ブレークポイントを設定することもできます。詳細については、Sun WorkShop オンラインヘルプの「デバッグウィンドウの使い方」の「指定変数の値変更時に停止」を参照してください。
dbxは、自動的なステップ実行を行い、各ステップで値を検査することによって、stop changeを実現しています。ライブラリが-gオプションでコンパイルされていない場合、ステップ実行では、ライブラリ呼び出しはスキップされます。したがって、制御の流れが次のようになっているとき、トレース時にライブラリ呼び出しと入れ子になったuser_routine2の呼び出しがスキップされるため、dbxは入れ子になったuser_-routine2をトレースしません。
user_routine callslibrary_routine, which callsuser_routine2, which changes variablevariable の値の変更は、
user_routine2の途中ではなく、ライブラリ呼び出しから復帰した後に発生します。
dbxは、ブロック局所変数、すなわち{}内で入れ子に定義された変数の変化に対するブレークポイントは設定できません。このような変数にブレークポイント (またはトレース) を設定しようとすると、その操作ができないことを示すエラーメッセージが出されます。指定した条件が発生した場合に実行を停止する
条件文が真になったときにプログラムの実行を停止するには、次のように入力します。
(dbx)stop condcondition「ブレークポイント」ウィンドウで、カスタムの「指定条件成立時」ブレークポイントを設定することもできます。詳細については、Sun WorkShop オンラインヘルプの「デバッグウィンドウの使い方」の「指定条件成立時カスタムブレークポイントの設定」を参照してください。
高速
modifyイベントウォッチポイントは、
modifyイベントを使用すると簡単に設定できます。Sun WorkShop オンラインヘルプの「dbx コマンドの使い方」の「定義済みイベント」を参照してください。
modifyイベントは、プログラムを自動的にステップ実行する代わりに、はるかに高速のページ保護構造を使用します。処理速度は、デバッグ中のプログラムのシステム呼び出し率だけでなく、監視中の変数の存在するページが何回修正されるかによって異なります。ブレークポイントフィルタを設定する
dbxでは、イベント管理コマンドのほとんどで (省略可能な) イベントフィルタの修飾文も利用することができます。最も単純なフィルタは次のいずれかの時点で、dbxに対してある特定の条件をテストするように指示します。イベント修飾子についての詳細は、「イベント指定のための修飾子」を参照してください。このフィルタ条件が真 (非 0) と評価されると、イベントコマンドが適用されます。条件が偽 (0) と評価されると、
dbxはイベントが発生しなかったかのようにプログラムの実行を続けます。条件つきフィルタを含む行または関数にブレークポイントを設定するためには、
-ifcondition 指示子文をstopコマンドまたはtraceコマンドの終わりに追加します。condition には、任意の有効な式を指定できます。コマンドの入力時に有効だった言語で書かれた、ブール値または整数値を返す関数呼び出しも有効な式に含まれます。
注 -inやatなど位置にもとづくブレークポイントでは、スコープはブレークポイント位置のスコープになります。それ以外の場合、イベントではなくエントリ発生時のスコープになります。スコープを正確に指定する構文を使用しなければならないことがあります。
stop in foo -if a>5stop cond a>5前者は
fooにブレークポイントが設定され、条件を検査します。後者は自動的に条件を検査します。最初のうちは、条件付イベントコマンド (watch タイプのコマンド) の設定と、フィルタの使用とを混同してしまうかもしれません。概念的には、watch タイプのコマンドは、各行の実行前に検査される前提条件を作成します (watch のスコープ内で)。ただし、条件付トリガーのあるブレークポイントコマンドでも、それに接続するフィルタを持つことができます。
(dbx)stop modify &speed -if speed==fast_enoughこのコマンドは、変数 speed を監視するように
dbxに指令します。speed に書き込みが行われると、-ifフィルタが有効になります。dbxは speed の新しい値がfast_enoughと等しいかどうかチェックします。等しくない場合、プログラムは実行を継続し、stopを「無視」します。
dbx構文では、フィルタはブレークの「事後」、構文の最後で[-ifcondition]文の形式で指定されます。
stop infunction[-ifcondition]イベント効率
デバッグ中のプログラムの実行時間に関するオーバーヘッドの量はイベントの種類によって異なります。最も単純なブレークポイントのように、実際はオーバーヘッドが何もないイベントもあります。1 つのブレークポイントしかないイベントも、オーバーヘッドは最小です。
実際のブレークポイントがときには何百にもなることのある多重ブレークポイント (
inclassなど) は、コマンド発行時にのみオーバーヘッドがあります。これは、dbxが永続的ブレークポイントを使用するためです。永続的ブレークポイントは、プロセスに常に保持され、停止するたびに取り除かれたり、contのたびに置かれたりすることはありません。
注 -stepおよびnextの場合、デフォルトでは、プロセスが再開される前にすべてのブレークポイントが取り除かれ、ステップが完了するとそれらは再び挿入されます。したがって、多くのブレークポイントを使用したり、多くのクラスで多重ブレークポイントを使用したりしているとき、stepおよびnextの速度は大幅に低下します。dbxenv変数step_eventsを使用して、stepやnextのたびにブレークポイントを取り除いたり、挿入し直したりするかどうかを制御することができます。
自動ステップ実行を利用するイベントは最も低速です。これは、各ソース行をステップ実行する単純な
tracestepコマンドの場合と同様にはっきりしています。一方、stopchangeexpression やtracecondvariable (ウォッチポイントと呼ばれるイベントのクラス) のようなイベントは、自動的にステップ実行するだけでなく、各ステップで式 expression や変数 variable を評価する必要があります。これらのイベントは非常に低速ですが、イベントと修飾語
-inを使用した関数とを結び付けることで、効率が上がることがよくあります。たとえば、次のようにします。
trace next -in mumblestop change clobbered_variable -in lookup
trace -in mainを使用しないでください。これは、mainによって呼び出された関数の中でも、トレースが有効になるためです。関数lookup()が変数の値を頻繁に変更すると思われる場合には、この方法を使用してください。
| サン・マイクロシステムズ株式会社 Copyright information. All rights reserved. | ホーム | 目次 | 前ページへ | 次ページへ | 索引 |