Oracle Solaris Studio 12.4 Man Pages

印刷ビューの終了

更新: January 2015
 
 

ctrace(1)

名前

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

形式

ctrace [options] [file]

説明

The ctrace command allows the user to monitor the sequential execution of a C program as each program statement executes. The effect is similar to executing a shell procedure with the -x option. ctrace reads the C program in file (or from standard input if the user does not specify file), inserts statements to print the text of each executable statement and the values of all variables referenced or modified, and writes the modified program to the standard output. The output of ctrace must be placed into a temporary file because the cc(1) commands do not allow the use of a pipe. This file can then be compiled and executed.

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

一般的に使用されるオプションは次のとおりです。

-f functions

指定された関数 functions だけをトレースします。

-v functions

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

変数を出力するためのデフォルトの書式に、別の書式を追加したいことがあります。デフォルトでは、long 変数とポインタ変数は常に符号付き整数として出力されます。文字配列を指すポインタは、適切であれば文字列として出力されます。charshort、および int 変数も符号付き整数として出力され、適切であれば文字として出力されます。double 変数は、科学的記数法の浮動小数点数として出力されます。次のオプションを使って、変数を別の書式で (その書式が適切であれば) 出力するように要求できます。

-o

8 進

-x

16 進

-u

符号なし

-e

浮動小数点

これらのオプションは特殊な状況でのみ使用されます。

-l n

デフォルトの 20 回ではなく n 回連続して実行された文をループと見なします。ループからすべてのトレース出力を取得するには 0 を使用してください。

-s

単純な代入文と文字列コピー関数の呼び出しによる冗長なトレース出力を抑止します。このオプションを使用すると、演算子 == の代わりに = が使われたことによるバグを見つけにくくなる可能性があります。

-t n

1 文あたり、デフォルトの 10 個ではなく n 個の変数をトレースします (最大値は 20)。このオプションをどのような場合に使用するかについては、診断セクションを参照してください。

-P

Preprocess the input before tracing it. The user can also use the -D, -I, and -U cc(1) options.

-p string

トレース出力関数をデフォルトの printf から変更します。たとえば、fprintf(stderr を指定すると、トレースの内容は標準エラー出力に送られます。

-r f

トレース関数パッケージ runtime.c の代わりに、ファイル f を使用します。この置き換えを使用すると、名前と先頭の引数だけではなく、出力関数全体を変更できます (-p オプションを参照)。

-V

バージョン情報を標準エラーに出力します。

-Qarg

argy のとき、ctrace に関する識別情報が出力ファイルに追加されます。これはソフトウェア管理に役立ちます。argn を明示的に指定すると、そのような情報は要求されません (これがデフォルトの動作です)。

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

 
1 #include <stdio.h>
2 main() /* count lines in input */
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
(cntl-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

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

トレース出力から、7 行目では変数 c に値 '1' が代入されているのに、8 行目では値が '\n' になっていることがわかります。if 文に注目することができれば、等価演算子 (==) の代わりに代入演算子 (=) が使用されていることに気づくはずです。この誤りはコードリーディングの際に見逃しやすいものです。

実行時のトレース制御

実行時のトレース制御

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

プログラムに関数 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 に設定することによって、それぞれトレースをオンまたはオフにすることができます。このオン/オフのオプションは、これらの関数を直接呼び出すことができないデバッガを使用している場合に利用できます。

ファイル

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

関連項目

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

診断

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

ctrace の診断

warning: some variables are not traced in this statement

C コンパイラからの「out of tree space; simplify expression」というエラーを避けるため、各文につき変数は 10 個までしかトレースされません。この数を増やすには、-t オプションを使用します。

warning: statement too long to trace

この文の長さが 400 文字を超えています。コードのインデントには、スペースではなくタブを使用してください。

cannot handle preprocessor code, use -P option

通常、C の文の途中にプリプロセッサ文 #ifdef/#endif があるか、プリプロセッサ文 #define の最後にセミコロンが置かれていることが原因です。

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

possible syntax error, try -P option

-P オプションと適切なプロセッサオプション (-D-I-U) を使って、ctrace の入力を前処理してください。

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

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

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

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

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