ctrace(1) SDK R4.11 ctrace(1)
NAME
ctrace - trace a C program to debug it
SYNOPSIS
ctrace [ options ] [ file ]
DESCRIPTION
Ctrace lets you follow the execution of a C program, statement by
statement. 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 you omit 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.
You must put the output of ctrace into a temporary file because the
cc(1) command does not allow the use of a pipe. You then compile and
execute this file.
As each statement in the program executes, it is listed at the
terminal, followed by the name and value of any variables referenced
or modified in the statement, followed by any output from the
statement. Loops in the trace output are detected and tracing is
stopped until the loop is exited or a different sequence of
statements within the loop is executed. A warning message is printed
every 1000 times through the loop to help you detect infinite loops.
The trace output goes to the standard output so you can put it into a
file for examination with an editor or the bfs(1) or tail(1)
commands.
Commonly used options are:
-f functions Trace only these functions.
-v functions Trace all but these functions.
You may want to add to the default formats for printing variables.
Long and pointer variables are always printed as signed integers.
Pointers to character arrays are also printed as strings if
appropriate. Char, short, and int variables are also printed as
signed integers and, if appropriate, as characters. Double variables
are printed as floating point numbers in scientific notation. The
options that print variables in additional formats are:
-o Octal
-x Hexadecimal
-u Unsigned
-e Floating point
Other options for special circumstances are:
-l n Check n consecutively executed statements for looping trace
output, instead of the default of 20. Use 0 to get all the
trace output from loops.
-s Suppress redundant trace output from simple assignment
statements and string copy function calls. This option can
hide a bug caused by using the = operator in place of the ==
operator.
-t n Trace n variables per statement instead of the default of 10
(the maximum number is 20). The DIAGNOSTICS section below
explains when to use this option.
-P Run the C preprocessor on the input before tracing it. You
can also use the -D, -I, and -U cc(1) preprocessor options.
The options that tailor the run-time trace package for the traced
program to run in a non-UNIX system environment are:
-p 'string'
Change the trace print function from the default of 'printf('.
For example, 'fprintf(stderr,' would send the trace to the
standard error output.
-r f Use file f in place of the runtime.c trace function package.
This lets you change the entire print function, instead of
just the name and leading arguments (see the -p option).
-Qarg If arg is y, identification information about ctrace will be
added to the output files. This can be useful for software
administration. Giving n for arg explicitly asks for no such
information, which is the default behavior.
-V Prints version information on the standard error.
EXAMPLES
If the file lc.c contains the following C program:
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 }
and you enter the following commands and test data:
cc lc.c
a.out
1
(ctrl-d)
the program will be compiled and executed.
The output of the program will be the number 2, which is not correct
because there is only one line in the test data. The error in this
program is common, but subtle.
If you invoke ctrace with these commands:
ctrace lc.c >temp.c
cc temp.c
a.out
the output will be:
2 main()
6 nl = 0;
/* nl == 0 */
7 while ((c = getchar()) != EOF)
The program is now waiting for input. If you enter the same test
data as before, the output will be:
/* 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)
If you now enter an end of file character (ctrl-d), the final output
will be:
/* c == -1 */
10 printf("%d\n", nl);
/* nl == 2 */2
/* return */
Note the program output printed at the end of the trace line for the
nl variable. Also note the return comment added by ctrace at the end
of the trace output. This comment shows the implicit return at the
terminating brace in the function.
The trace output shows that variable c is assigned the value 1 in
line 7, but `\n' in line 8. Once your attention is drawn to the if
statement in line 8, you will probably realize that you used the
assignment operator (=) in place of the equal operator (==). You can
easily miss this error during code reading.
Execution-time Trace Control
The default operation for ctrace is to trace the entire program file,
unless you use the -f or -v options to trace specific functions. The
default does not give you statement by statement control of the
tracing, nor does it let you turn the tracing off and on when
executing the traced program.
You can do both of these by adding ctroff() and ctron() function
calls to your program to turn the tracing off and on, respectively,
at execution time. Thus, you can code arbitrarily complex criteria
for trace control with if statements, and you can even conditionally
include this code because ctrace defines the CTRACE preprocessor
variable. For example:
#ifdef CTRACE
if (c == '!' && i > 1000)
ctron();
#endif
These functions can also be called from symbolic debuggers such as
mxdb(1) or dbx(1) if they are compiled with the -g option. For
example, to trace all but lines 7 to 10 in the main function, enter:
mxdb a.out
b 7, action {eval ctroff(); c}
b 11, action {eval ctron(); c}
c
You can also turn the trace off and on by setting the static variable
tr_ct_ to 0 and 1, respectively.
FILES
runtime.c run-time trace package
DIAGNOSTICS
warning: some variables are not traced in this statement
Only 10 variables are traced in a statement to prevent the C
compiler "out of tree space; simplify expression" error. Use
the -t option to increase this number.
warning: statement too long to trace
This statement is over 400 characters long. Make sure that
you are using tabs to indent your code, not spaces.
cannot handle preprocessor code, use -P option
This is usually caused by #ifdef/#endif preprocessor
statements in the middle of a C statement, or by a semicolon
at the end of a #define preprocessor statement.
'if ... else if' sequence too long
Split the sequence by removing an else from the middle.
possible syntax error, try -P option
Use the -P option to preprocess the ctrace input, along with
any appropriate -D, -I, and -U preprocessor options. If you
still get the error message, check the NOTES section below.
SEE ALSO
signal(2), ctype(3C), fflush(3S), longjmp(3C), printf(3S),
setjmp(3C), string(3C).
NOTES
You will get a ctrace syntax error if you omit the semicolon at the
end of the last element declaration in a structure or union, just
before the right brace (}). This is optional in some C compilers.
Defining a function with the same name as a system function may cause
a syntax error if the number of arguments is changed. Just use a
different name.
Ctrace assumes that BADMAG is a preprocessor macro, and that EOF and
NULL are #defined constants. Declaring any of these to be variables,
e.g., "int EOF;", will cause a syntax error.
Pointer values are always treated as pointers to character strings.
Ctrace does not know about the components of aggregates like
structures, unions, and arrays. It cannot choose a format to print
all the components of an aggregate when an assignment is made to the
entire aggregate. Ctrace may choose to print the address of an
aggregate or use the wrong format (e.g., 3.149050e-311 for a
structure with two integer members) when printing the value of an
aggregate.
The loop trace output elimination is done separately for each file of
a multi-file program. Separate output elimination can result in
functions called from a loop still being traced, or the elimination
of trace output from one function in a file until another in the same
file is called.
Licensed material--property of copyright holder(s)