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


第 11 章

修正継続機能 (fix と continue)

fix を使用すると、デバッグプロセスを停止しないで、編集されたソースコードを簡単に再コンパイルすることができます。

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

修正継続機能の使用

fixcontinue の各機能を使用すると、ソースファイルを修正して再コンパイルし、プログラム全体を作成しなおすことなく実行を続けることができます。.o ファイルを更新して、それらをデバッグ中のプログラムに組み込むことにより、再リンクの必要がなくなります。

この機能を使用する利点は次のとおりです。

fix と continue の働き

fix コマンドを使用するには、エディタウィンドウでソースを編集する必要があります (コードの変更方法については、「fix と continue によるソースの変更」参照)。変更結果を保存して fix と入力します。fix コマンドについては、Sun WorkShop オンラインヘルプの「dbx コマンドの使い方」の「fix コマンド」を参照してください。

fix が実行されると、dbx は適切なコンパイラオプションでコンパイラを呼び出します。変更後のファイルがコンパイルされ、一時共有オブジェクト (.so) ファイルが作成されます。古いファイルと新しいファイルとを比較することによって、修正の安全性を検査する意味上のテストが行われます。

実行時リンカーを使用して新しいオブジェクトファイルが動作中のプロセスにリンクされ、プログラムカウンタが古い関数から新しい関数の同じ行に移動します (その関数が修正中のスタックの 1 番上にある場合)。さらに、古いファイルのブレークポイントがすべて新しいファイルに移動します。

対象となるファイルがデバッグ情報つきでコンパイルされているかどうかに関わらず、fixcont を実行できます。ただし、デバッグ情報なしでコンパイルされているファイルの場合には多少の機能制限があります。Sun WorkShop オンラインヘルプの「dbx コマンドの使い方」の「fix コマンド」の -g オプションの解説を参照してください。

共有オブジェクト (.so) ファイルの修正は可能ですが、その場合、そのファイルを特別なモードでオープンする必要があります。dlopen 関数の呼び出しで、RTLD_NOW|RTLD_GLOBAL または RTLD_LAZY|RTLD_GLOBAL のどちらかを使用します。

fix と continue によるソースの変更

fixcontinue を使用すると、ソースを次の方法で変更できます。

古いファイルから新しいファイルに関数をマップすると問題が起きることがあります。ソースファイルの編集時にこのような問題の発生を防ぐには、次のことを守ってください。

上記の変更を行う場合は、fix と continue で処理するよりプログラム全体を作りなおす方が簡単です。

プログラムの修正

変更後にソースファイルを再リンクするとき fix コマンドを使用すればプログラム全体を再コンパイルしなくて済みます。引き続きプログラムの実行を続けることができます。

ファイルを修正するには、次の手順に従ってください。

1. 変更をソースファイルに保存します。

この手順を忘れても、Sun WorkShop では自動的に変更が保存されます。

2. dbx プロンプトで fix と入力します。

修正は無制限に行うことができますが、1 つの行でいくつかの修正を行った場合は、プログラムを作成しなおすことを考えてください。fix コマンドは、メモリー内のプログラムのイメージを変更しますが、ディスク上のイメージは変更しません。また修正を行うと、メモリーのイメージは、ディスク上のイメージと同期しなくなります。

fix コマンド は、実行可能ファイル内での変更ではなく、.o ファイルとメモリーイメージの変更だけを行います。プログラムのデバッグを終了したら、プログラムを作成しなおして、変更内容を実行可能ファイルにマージする必要があります。デバッグを終了すると、プログラムを作成しなおすように指示するメッセージが出されます。

-a 以外のオプションを指定し、ファイル名引数なしで fix コマンドを実行すると、現在変更を行なったソースファイルだけが修正されます。

fix を実行すると、コンパイル時にカレントであったファイルの現在の作業ディレクトリが検索されてからコンパイル行が実行されます。したがってコンパイル時とデバッグ時とでファイルシステム構造が変化すると正しいディレクトリが見つからなくなることがあります。これを防ぐには、pathmp コマンドを使用します。これは 1 つのパス名から別のパス名までのマッピングを作成するコマンドです。マッピングはソースパスとオブジェクトファイルパスに適用されます。

修正後の続行

プログラムの実行を継続するには、cont コマンドを使用します (Sun WorkShop オンラインヘルプの「dbx コマンドの使い方」の「cont コマンド」参照)。

プログラムの実行を再開するには、変更による影響を判断するための以下の条件に注意してください。

実行された関数への変更

すでに実行された関数に変更を加えた場合、その変更内容は次のことが起こるまで無効です。

変数への単純な変更以上のことを修正した場合は、fix コマンドに続けて run コマンドを使用してください。run コマンドを使用すると、プログラムの再リンクが行われないため処理が速くなります。

呼び出されていない関数への変更

呼び出されていない関数に変更を加えた場合、変更内容は、その関数が呼び出されたときに有効になります。

現在実行中の関数への変更

現在実行中の関数に変更を加えた場合、fix コマンドの影響は、変更内容が停止した関数のどの場所に関連しているかによって異なります。

現在スタック上にある関数への変更

停止された関数ではなく、現在スタック上にある関数に変更を加えた場合、変更されたコードは、その関数の現在の呼び出しでは使用されません。停止した関数から戻ると、スタック上の古いバージョンの関数が実行されます。

この問題を解決する方法はいくつかあります。

スタック上の修正された関数にブレークポイントがある場合、このブレークポイントは、新しいバージョンの関数に移動します。古いバージョンが実行される場合、プログラムはこれらの関数で停止しません。

修正後の変数の変更

大域変数への変更は、pop コマンドでも fix コマンドでも取り消されません。大域変数に正しい値を手作業で再び割り当てるには、assign コマンドを使用してください。(Sun WorkShop オンラインヘルプの「dbx コマンドの使い方」の「assign コマンド」参照)。

以下の例は、修正継続機能を使用して簡単なバグを修正する方法を示しています。6 行目で NULL ポインタを逆参照しようとしたときに、セグメンテーションエラーが発生します。

(dbx) list 1,$
    1   #include<stdio.h>
    2   
    3   char *from = "ships";
    4   void copy(char *to)
    5   {
    6   while ((*to++ = *from++) != '\0');
    7   *to = '\0';
    8   }
    9   
   10   main()
   11   {
   12   char buf[100];
   13   
   14   copy(0);
   15   printf("%s\n", buf);
   16   return 0;
   17   }
(dbx) run
実行中: testfix 
(プロセス id 11667)
シグナル SEGV (フォルトのアドレスにマッピングしていません) 関数 copy 行番
号 6  ファイル "testfix.c"
    6   while ((*to++ = *from++) != '\0');

edit でファイルの編集をします。14 行目を 0 ではなく buf をコピー (copy) するように変更し、fix を実行します。

(dbx) edit
# エディタが起動します。 
   14  copy(0);# 変更前
   14  copy(buf);# 変更後
# エディタを保存して終了します。
(dbx) fix
修正中  "testfix.c" ......
 pc は "testfix.c":6  に移動しました
copy で停止しました 行番号 6  ファイル "testfix.c"
    6      while ((*to++ = *from++) != '\0');

ここでプログラムを続行しても、NULL ポインタがスタックをプッシュしているためセグメント例外が返されます。pop コマンドを使用して、スタックフレームを 1 つ上がってください。

(dbx) pop
main で停止しました 行番号 14  ファイル "testfix.c"
   14   copy(buf);

ここでプログラムを続行すると、プログラムは実行されますが、大域変数 from がすでに増分されているため正しい値が出力されません。assign コマンドを使用して大域変数を復元し、続行してください。プログラムは次のように正しい値を表示します。assign コマンドを使用しないと、プログラムは ships と表示すべきところを hips と表示します。

(dbx) assign from = from-1
(dbx) cont
ships

ヘッダファイルの変更

場合によってはソースファイルだけでなくヘッダ (.h) ファイルも変更することがあります。変更したヘッダファイルをインクルードしている、プログラム内のすべてのソースファイルから、それらのヘッダファイルをアクセスするには、そのヘッダファイルをインクルードしているすべてのソースファイルのリストを引数として fix コマンドに渡す必要があります。ソースファイルのリストを指定しなければ、主要ソースファイルだけが再コンパイルされ、変更したヘッダファイルは主要ソースファイルにしかインクルードされず、プログラムの他のソースには変更前のヘッダファイルがインクルードされたままになります。

C++ テンプレート定義の修正

C++ テンプレート定義は直接修正できないので、これらのファイルはテンプレートインスタンスで修正します。テンプレート定義ファイルを変更しなかった場合に日付チェックを上書きするには、-f オプションを使用します。dbx によるテンプレート定義 .o ファイルの検索範囲は、デフォルトのリポジトリディレクトリ SunWS_cache です。dbxfix コマンドは -ptr コンパイラスイッチをサポートしていません。


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