dbx コマンドによるデバッグ ホーム目次前ページへ次ページへ索引


第 5 章

ブレークポイントとトレースの設定

ブレークポイントは、アクションが発生する場所であり、そのポイントでプログラムは実行を停止します。トレースを設定することにより、変数の値の変更など、プログラムでのイベントに関する情報を表示することができます。トレースの動作は、ブレークポイントの動作とは異なりますが、トレースとブレークポイントは同様のイベントハンドラを共有します。

この章では、ブレークポイントとトレースの設定方法とウォッチポイントの使用方法について説明します。

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

ブレークポイントを設定する

dbx では、ソースレベルのブレークポイントを設定するため、3 種類のブレークポイントアクションコマンドを使用することができます。

マシンレベルのブレークポイントを設定するには、stopiwhenitracei コマンドを使用します (第 17 章を参照)。

ソースコードの特定の行に stop ブレークポイントを設定する

dbx stop at コマンドを使用して、行番号にブレークポイントを設定します。ここで、n はソースコードの行番号、filename は任意のプログラムファイル名修飾子です。

(dbx) stop at filename: n

ここで、n はソースコードの行番号、filename はそのコードが含まれているソースファイルの名前 (省略可能) です。たとえば、次のようにします。

(dbx) stop at main.cc:3

stop または when コマンドに指定された行が、ソースコードの実行可能行ではない場合、dbx は次の有効な実行可能行にブレークポイントを設定します。実行可能な行がない場合、dbx はエラーを出します。

「ブレークポイント」ウィンドウ内でもブレークポイントを設定できます。詳細については、Sun WorkShop オンラインヘルプの「デバッグウィンドウの使い方」の「ブレークポイント (行に設定)」を参照してください。

関数に stop ブレークポイントを設定する

dbx stop in コマンドを使用して、関数にブレークポイントを設定します。

(dbx) stop in function

指定関数中で停止するブレークポイントは、プロシージャまたは関数の最初のソース行の冒頭でプログラムの実行を中断します。

「デバッグ」ウィンドウで、関数にブレークポイントを設定することもできます。詳細については、Sun WorkShop オンラインヘルプの「デバッグウィンドウの使い方」の「ブレークポイント (関数に設定)」を参照してください。

dbx は、以下の場合を除いては、ユーザーが参照している変数または関数を決定します。

次の例を考えてみましょう。

int foo(double);
 int foo(int);

 int bar();

 class x {

    int bar();

};

メンバーでない関数で停止する場合、次のように入力して、

stop in foo(int)

グローバル関数 foo(int) にブレークポイントを設定します。

メンバー関数にブレークポイントを設定するには、次のコマンドを使用します。

stop in x::bar()

次のように入力すると、

stop in foo

dbx は、ユーザーがグローバル関数 foo(int)、グローバル関数 foo(double) のどちらを意味しているのかを判断することができず、明確にするため、オーバーロードしたメニューを表示する場合があります。

次のように入力すると、

stop in ''bar

dbx は、ユーザーがグローバル関数 bar()、メンバー関数 bar() のどちらを意味しているのかを判断することができないため、オーバーロードしたメニューを表示します。

特定の行に when タイプのブレークポイントを設定する

when タイプのブレークポイントは、ほかの dbx コマンドを副作用コマンドとして利用できます。たとえば、whenlist コマンドを副作用コマンドとして用いれば、独自のトレースを実現することができます。

(dbx) when at 123 { list $lineno;}

whencont コマンドを暗黙指定して動作します。上の例の場合、現在行のコードを出力した後、プログラムの実行が続けられます。

動的にリンクされたライブラリにブレークポイントを設定する

実行時リンカーとの間でプログラムインタフェースを使用するコード、すなわち
dlopen()dlclose()、およびそれらに関連する関数を呼び出すコードをデバッグするときは、dbx の全機能を利用できます。実行時リンカーは、プログラムの実行中に共有ライブラリをリンクしたり、そのリンクを解除したりします。dlopen()
dlclose() のサポートにより、動的にリンクされている共有ライブラリの関数もプログラムの起動時にリンクされたライブラリの関数と同様に、ステップ実行したり、ブレークポイントを設定したりできます。

例外が 3 つあります。

C++ プログラムに複数のブレークポイントを設定する

異なるクラスのメンバー関数の呼び出し、特定のクラスのすべてのメンバー関数の呼び出し、または多重定義されたトップレベル関数の呼び出しに関連する問題が発生する可能性があります。このような場合に対処するために、inmemberinclassinfunction または inobject のキーワードのうちの 1 つを stop, when,または trace コマンドとともに使用することにより、1 回のコマンドで C++ コードに複数のブレークポイントを挿入できます。

異なるクラスのメンバー関数にブレークポイントを設定する

特定のメンバー関数のオブジェクト固有のもの (同じメンバー関数名でクラスの異なるもの) それぞれにブレークポイントを設定するには、stop inmember を使用します。

when ブレークポイントを設定するには、when コマンドをキーワード inmember とともに使用します。

たとえば、関数 draw が複数の異なるクラスに定義されている場合は、それぞれの関数ごとにブレークポイントを設定します。

(dbx) stop inmember draw

「ブレークポイント」ウィンドウで、「指定メンバー中で」ブレークポイントを設定することもできます。詳細については、Sun WorkShop オンラインヘルプの「デバッグウィンドウの使い方」の「指定メンバー中でブレークポイントの設定」を参照してください。

同じクラスのメンバー関数にブレークポイントを設定する

特定のクラスのすべてのメンバー関数にブレークポイントを設定するには、stop inclass コマンドを使用します。

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 コマンドの基本構文は次の通りです。

trace event-specification [ modifier ]

トレースコマンドの完全な構文については、Sun WorkShop オンラインヘルプの「dbx コマンドの使い方」の「trace コマンド」を参照してください。

「ブレークポイント」ウィンドウで、トレースを設定することもできます。詳細については、Sun WorkShop オンラインヘルプの「デバッグウィンドウの使い方」の「トレースの設定」を参照してください。

トレースで提供される情報は、トレースに関連する event の型に依存します (「イベント指定の設定」を参照)。

トレース速度を制御する

多くのプログラムは高速に実行されるため、表示がよく見えません。環境変数 dbxenv trace_speed を使用して、トレーススコープ内の各行の実行間隔を制御することができます。デフォルトの実行間隔は 0.5 秒です。

トレース時の各行の実行間隔を設定するには、次のように入力します。

dbxenv trace_speed number

「デバッグオプション」ダイアログで、トレースの実行速度を設定することもできます。詳細については、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

stop modify を使用するときの注意事項

「ブレークポイント」ウィンドウで、「指定範囲変更時」ブレークポイントを設定することもできます。詳細については、Sun WorkShop オンラインヘルプの「デバッグウィンドウの使い方」の「指定範囲変更時に停止」を参照してください。

指定した変数の値が変化したときに実行を停止する

指定した変数の値が変化したときにプログラムの実行を停止するには、次のように入力します。

(dbx) stop change variable

stop change を使用するときの注意事項

「ブレークポイント」ウィンドウで、「指定変数の値変更時」ブレークポイントを設定することもできます。詳細については、Sun WorkShop オンラインヘルプの「デバッグウィンドウの使い方」の「指定変数の値変更時に停止」を参照してください。
dbx は、自動的なステップ実行を行い、各ステップで値を検査することによって、stop change を実現しています。ライブラリが -g オプションでコンパイルされていない場合、ステップ実行では、ライブラリ呼び出しはスキップされます。したがって、制御の流れが次のようになっているとき、トレース時にライブラリ呼び出しと入れ子になった user_routine2 の呼び出しがスキップされるため、dbx は入れ子になった user_-routine2 をトレースしません。

   user_routine calls
      library_routine, which calls
        user_routine2, which changes variable

variable の値の変更は、user_routine2 の途中ではなく、ライブラリ呼び出しから復帰した後に発生します。

dbx は、ブロック局所変数、すなわち {} 内で入れ子に定義された変数の変化に対するブレークポイントは設定できません。このような変数にブレークポイント (またはトレース) を設定しようとすると、その操作ができないことを示すエラーメッセージが出されます。

指定した条件が発生した場合に実行を停止する

条件文が真になったときにプログラムの実行を停止するには、次のように入力します。

(dbx) stop cond condition

「ブレークポイント」ウィンドウで、カスタムの「指定条件成立時」ブレークポイントを設定することもできます。詳細については、Sun WorkShop オンラインヘルプの「デバッグウィンドウの使い方」の「指定条件成立時カスタムブレークポイントの設定」を参照してください。

高速 modify イベント

ウォッチポイントは、modify イベントを使用すると簡単に設定できます。Sun WorkShop オンラインヘルプの「dbx コマンドの使い方」の「定義済みイベント」を参照してください。

modify イベントは、プログラムを自動的にステップ実行する代わりに、はるかに高速のページ保護構造を使用します。処理速度は、デバッグ中のプログラムのシステム呼び出し率だけでなく、監視中の変数の存在するページが何回修正されるかによって異なります。

ブレークポイントフィルタを設定する

dbx では、イベント管理コマンドのほとんどで (省略可能な) イベントフィルタの修飾文も利用することができます。最も単純なフィルタは次のいずれかの時点で、dbx に対してある特定の条件をテストするように指示します。イベント修飾子についての詳細は、「イベント指定のための修飾子」を参照してください。

このフィルタ条件が真 (非 0) と評価されると、イベントコマンドが適用されます。条件が偽 (0) と評価されると、dbx はイベントが発生しなかったかのようにプログラムの実行を続けます。

条件つきフィルタを含む行または関数にブレークポイントを設定するためには、-if condition 指示子文を stop コマンドまたは trace コマンドの終わりに追加します。

condition には、任意の有効な式を指定できます。コマンドの入力時に有効だった言語で書かれた、ブール値または整数値を返す関数呼び出しも有効な式に含まれます。


注 - inat など位置にもとづくブレークポイントでは、スコープはブレークポイント位置のスコープになります。それ以外の場合、イベントではなくエントリ発生時のスコープになります。スコープを正確に指定する構文を使用しなければならないことがあります。

たとえば、次の 2 つのフィルタは異なります。

stop in foo -if a>5
stop cond a>5

前者は foo にブレークポイントが設定され、条件を検査します。後者は自動的に条件を検査します。

最初のうちは、条件付イベントコマンド (watch タイプのコマンド) の設定と、フィルタの使用とを混同してしまうかもしれません。概念的には、watch タイプのコマンドは、各行の実行前に検査される前提条件を作成します (watch のスコープ内で)。ただし、条件付トリガーのあるブレークポイントコマンドでも、それに接続するフィルタを持つことができます。

次に具体的な例を示します。

(dbx) stop modify &speed -if speed==fast_enough

このコマンドは、変数 speed を監視するように dbx に指令します。speed に書き込みが行われると、-if フィルタが有効になります。dbxspeed の新しい値が fast_enough と等しいかどうかチェックします。等しくない場合、プログラムは実行を継続し、stop を「無視」します。

dbx 構文では、フィルタはブレークの「事後」、構文の最後で [-if condition] 文の形式で指定されます。

stop in function [-if condition]

イベント効率

デバッグ中のプログラムの実行時間に関するオーバーヘッドの量はイベントの種類によって異なります。最も単純なブレークポイントのように、実際はオーバーヘッドが何もないイベントもあります。1 つのブレークポイントしかないイベントも、オーバーヘッドは最小です。

実際のブレークポイントがときには何百にもなることのある多重ブレークポイント (inclass など) は、コマンド発行時にのみオーバーヘッドがあります。これは、dbx が永続的ブレークポイントを使用するためです。永続的ブレークポイントは、プロセスに常に保持され、停止するたびに取り除かれたり、cont のたびに置かれたりすることはありません。


注 - step および next の場合、デフォルトでは、プロセスが再開される前にすべてのブレークポイントが取り除かれ、ステップが完了するとそれらは再び挿入されます。したがって、多くのブレークポイントを使用したり、多くのクラスで多重ブレークポイントを使用したりしているとき、step および next の速度は大幅に低下します。dbxenv 変数 step_events を使用して、stepnext のたびにブレークポイントを取り除いたり、挿入し直したりするかどうかを制御することができます。

自動ステップ実行を利用するイベントは最も低速です。これは、各ソース行をステップ実行する単純な trace step コマンドの場合と同様にはっきりしています。一方、stop change expressiontrace cond variable (ウォッチポイントと呼ばれるイベントのクラス) のようなイベントは、自動的にステップ実行するだけでなく、各ステップで式 expression や変数 variable を評価する必要があります。

これらのイベントは非常に低速ですが、イベントと修飾語 -in を使用した関数とを結び付けることで、効率が上がることがよくあります。たとえば、次のようにします。

trace next -in mumble
stop change clobbered_variable -in lookup

trace -in main を使用しないでください。これは、main によって呼び出された関数の中でも、トレースが有効になるためです。関数 lookup() が変数の値を頻繁に変更すると思われる場合には、この方法を使用してください。


サン・マイクロシステムズ株式会社
Copyright information. All rights reserved.
ホーム   |   目次   |   前ページへ   |   次ページへ   |   索引