マニュアルページ ctrace.1




名前

     ctrace - C プログラム・デバッガ


形式

     ctrace [options] [file]


機能説明

     ctrace コマンドを使用すると、C プログラムの実行を文単位で 監
     視することができます。これには、 -x オプション付きでシェル手
     続きを実行した場合と同様の効果があります。 ctrace は、ファイ
     ル  ( file が指定されていない場合は標準入力) から C プログラ
     ムを読み取り、各実行可能文とそこで参照または変更されるすべて
     の変数の値を出力する文を挿入し、その結果のプログラムを標準出
     力に書き込みます。 cc(1) コマンドは ctrace の出力は一時 ファ
     イルに保存する必要があります。この一時ファイルは、コンパイル
     し、実行することができます。

     プログラム中の各文が実行されるたびに、端末上にその文の内容、
     そこで参照または変更された変数の名前と値、さらにその文による
     出力があればその内容が表示されます。トレース出力からはループ
     も検出され、その場合はループから抜けるかループ内で別のシーケ
     ンスが実行されるまでトレースが停止されます。無限ループを見つ
     けることができるように、ループが 1000 回繰り返されるたびに警
     告メッセージが出力されます。トレース出力は標準出力に書き込ま
     れ る ため、その内容をファイルに保存した後にエディタ、または
     tail(1) コマンドを使って調べることができます。

     共通に使われるオプションは次のとおりです。

     -f functions  指定された関数 functions だけをトレー ス し ま
                   す。
     -v functions  指定された関数 functions を除く、すべての関 数
                   をトレースします。

     変数を出力するためのデフォルトの書式に、別の書式を追加したい
     こ とがあります。デフォルトでは、long 変数とポインタ変数は常
     に符号付き整数として出力されます。文字配列を指すポインタは、
     適 切であれば文字列として出力されます。 char 変数、 short 、
     int 変数も符号付き整数として出力され、適切であれば文字として
     出力されます。 double 変数は、指数部付き表記の浮動小数点数と
     して出力されます。次のオプションを使って、各変数を上記以外の
     書式で (その書式が適切であれば) 出力することができます。

     -o     8 進数
     -x     16 進数
     -u     符号なし整数
     -e     浮動小数点数

     次のオプションは、特別な環境でのみ使用されます。

     -l n   n 回連続して実行された文をループと見なします。デ フォ
            ル ト値は 20 回です。0 を指定すると、ループからのすべ
            てのトレース出力が得られます。
     -s     単純な代入文と文字列コピー関数の呼び出しによる冗長 な
            ト レー ス 出力を抑止します。このオプションを使用する
            と、演算子 == の代わりに = が使われたことによるバグを
            見つけることができなくなります。
     -t n   1 文あたり n 個の変数をトレースします。デフォルト値は
            10  個です。 n の最大値は 20 です。このオプションをど
            のような場合に使用するかについては、「診断」の項を 参
            照してください。
     -P     トレースの前に、入力データの前処理を行いま す。 同 時
            に、 cc(1) のオプションである -D 、 -I 、 -U も使用で
            きます。
     -pstring
            トレース出力に使用する関数を指定します。デフォルト で
            は  printf  が 使 用 さ れ ます。たとえば、 string に
            fprintf(stderr) を指定すると、トレースの内容は標準 エ
            ラー出力に送られます。
     -rf    トレース関数パッケージ runtime.c の代わりに、ファイル
            f  を使用します。このオプションでファイルを置き換えれ
            ば、名前と先頭の引数だけではなく、出力関数全体を変 更
            することができます ( -p オプションを参照)。
     -V     バージョン情報を標準エラーに出力します。
     -Qarg  arg が y のとき、 ctrace に関する識別情報が出力ファイ
            ル に追加されます。この情報は、ソフトウェア管理に役立
            ちます。 arg に n を指定すると識別情報は出力されま せ
            ん (デフォルト)。


使用例

     ファイル lc.c に次の C プログラムが含まれているとします。

           1 #include <stdio.h>
           2 main() /* 入力の行数を数える */
           3 {
           4   int c, nl;
           5
           6   nl = 0;
           7   while ((c = getchar()) != EOF)
           8        if (c = '\n')
           9             ++nl;
          10   printf("%d\n", nl);
          11 }

     次のコマンドとテスト用データを入力します。

          cc lc.c
          a.out
          1
          (Ctrl-d)

     上記のプログラムがコンパイルされ、実行されます。結果として、
     2  という数字が出力されます。テスト用データには 1 行しか含ま
     れていないため、この結果は正しくないと言えます。このプログラ
     ムのような誤りを犯すことはよくありますが、なかなか見つけるこ
     とができません。そこで、次のように、 ctrace を呼び出し、作成
     されたプログラムをコンパイル、実行してみます。

          ctrace lc.c >temp.c
          cc temp.c
          a.out

     出力は次のようになります。

           2 main()
           6   nl = 0;
               /* nl == 0 */
           7   while ((c = getchar()) != EOF)

     プログラムは、ここで端末からの入力を待機します。上記と同じテ
     スト用データが入力されると、引き続き次のように出力します。

               /* c == 49 or '1' */
           8        if (c = '\n')
                    /* c == 10 or '\n' */
           9             ++nl;
                         /* nl == 1 */
           7   while ((c = getchar()) != EOF)
               /* c == 10 or '\n' */
           8        if (c = '\n')
                    /* c == 10 or '\n' */
           9             ++nl;
                         /* nl == 2 */
           7   while ((c = getchar()) != EOF)

     ここでファイルの終端を示す文字 (Ctrl-d) が入力されると、プロ
     グラムは次のように出力して終了します。

               /* c == -1 */
          10   printf("%d\n", nl);
               /* nl == 2 */2
                return

     最後から 2 行目の変数 nl のトレース行の終わりに出力される 情
     報 に 注目してください。また、トレース出力の最後に追加された
     return というコメントにも注目してください。これは、関数を 閉
     じる中括弧のところで、暗黙的に return が行われたことを示して
     います。

     トレース出力から、7 行目では変数 c に '1' が代入されたのに、
     8  行目でその値が '\n' になっていることが分かります。この if
     文に注目することができれば、おそらく等価演算子 ( == ) の代わ
     り に、誤って代入演算子 ( = ) が使用されていることに気づくは
     ずです。



実行時のトレース制御

     -f オプションまたは -v オプションでトレース対象の関数が指 定
     されないかぎり、 ctrace はプログラムファイル全体をトレースし
     ます。このデフォルトの動作では、文単位でトレースを制御 し た
     り、 ト レース後のプログラムを実行するときにトレースをオン /
     オフすることができません。

     プログラムに関数 ctroff() および ctron() の呼び出しを追加 す
     れ ば、 実 行 時 にこの 2 つの操作を行うことができます。関数
     ctroff() はトレースをオンに、 ctron() はトレースをオフにしま
     す。 こ のようにして、トレースを制御するための複雑な基準も、
     if 文を使って自由にコーディングすることができます。さら に、
     ctrace  で は 環境変数 CTRACE が定義されるため、次の例のよう
     に、トレースを制御するコードを条件付きで取り込むこともできま
     す。

          #ifdef CTRACE
               if (c == '!' && i > 1000)
                    ctron();
          #endif

     -g オプションでコンパイルすれば、これらの関数を dbx(1) か ら
     呼び出すことも可能です。たとえば、 main 関数の 7 行目から 10
     行目を除くすべての行をトレースするためには、次のように入力し
     ます。

          dbx a.out
          when at 7 {call ctroff();}
          when at 7 {call ctron();}
          run

     静的変数 tr_ct_ の設定値によってトレースをオン / オフする こ
     ともできます。 0 に設定するとトレースはオフ、 1 に設定すると
     オンになります。この方法は、上記の 2 つの関数を直接呼び出 す
     ことができないデバッガを使用している場合に利用できます。


ファイル

     runtime.c      実行時トレース・パッケージ


関連項目

     bfs(1), dbx(1), tail(1), ctype(3C), fclose(3S),  printf(3S),
     string(3C)


診断

     トレース後のコードには cc の警告メッセージが含まれることがあ
     る た め、 ここでは ctrace と cc(1) の両方から出力される診断
     メッセージを取り上げます。ごくまれに、 cc のエラーメッセージ
     を 受 け取ることもありますが、そのケースは避けることができま
     す。

  ctrace の診断メッセージ
     warning: some variables are not traced in this statement
          C コンパイラからの "out of tree space; simplify expres-
          sion"  というエラーを避けるため、デフォルトでは、各文に
          つき変数は 10 個までしかトレースできません。この数 は、
          -t オプションを使って増やすことができます。

     warning: statement too long to trace
          この文の長さが 400 文字を超えています。スペースを使って
          インデントが行われている場合は、それをタブに変えて 1 行
          あたりの文字数を少なくしてください。

     cannot handle preprocessor code, use -P option
          通常、C の文の途中に前処理文 #ifdef/#endif があるか、前
          処理文の最後にセミコロンが置かれていることが原因です。

          途中の else を削除して、シーケンスを分割してください。

     possible syntax error, try -P option
          -P オプションと適切な前処理オプション ( -D 、 -I 、  -U
          ) を使って、入力プログラムの前処理を行なってください。



注意事項

     システム関数と同じ名前で関数を定義した場合、その引数の数がシ
     ステム関数と異なっていると構文エラーになります。別の名前を使
     用してください。

     ctrace は、 BADMAG を前処理マクロ、  EOF  お よ び  NULL  を
     #define  で 定義された定数と見なします。" int EOF ; " のよう
     に、これらを変数として宣言すると構文エラーになります。

     ポインタ値は常に、文字列ポインタを指すポインタとして扱われま
     す。

     ctrace は、構造体、共用体、配列といった集合体の構成要素を 識
     別できません。集合体全体に代入が行われる場合、その集合体の全
     要素を出力するための書式を適切に選択できません。集合体のアド
     レスを出力したり、集合体の値を誤った書式で出力することがあり
     ます (たとえば、2 つの整数メンバーを持つ構造体を  3.149050e-
     311 のように出力します)。

     複数のファイルから構成されるプログラムの場合、ループによるト
     レー ス 出力の抑止は各ファイルごとに別々に行われます。そのた
     め、ループから呼び出される関数が繰り返しトレースされたり、あ
     る関数のトレースが同じファイル内の別の関数が呼び出されるまで
     抑止されることがあります。