# マニュアルページ 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 のように出力します)。

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