マニュアルページ 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 のように出力します)。
複数のファイルから構成されるプログラムの場合、ループによるト
レー ス 出力の抑止は各ファイルごとに別々に行われます。そのた
め、ループから呼び出される関数が繰り返しトレースされたり、あ
る関数のトレースが同じファイル内の別の関数が呼び出されるまで
抑止されることがあります。