ctrace(1) CLIX ctrace(1)
NAME
ctrace - Runs a C program debugger
SYNOPSIS
ctrace [flags] [file]
DESCRIPTION
The ctrace command is a C program debugger that allows you to follow the
execution of a C program, statement-by-statement. The effect is similar
to executing a shell procedure with the -x flag. The command ctrace reads
the C program in file (or from stdin if you do not specify file), inserts
statements to display the text of each executable statement and the values
of all variables referenced or modified, and writes the modified program
to stdout. You must put the output of ctrace into a temporary file
because the cc command does not allow the use of a pipe. You then compile
and execute this file.
As each statement in the program executes it will be 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 displayed every 1000 times through the
loop to help you detect infinite loops. The trace output goes to stdout
so you can put it into a file for examination with an editor or the bfs or
tail commands.
The flags commonly used are:
-ffunctions Trace only these functions.
-vfunctions Trace all but these functions.
You may want to add to the default formats for displaying variables. Long
and pointer variables are always displayed as signed integers. Pointers
to character arrays are also displayed as strings if appropriate. Char,
short, and int variables are also displayed as signed integers and, if
appropriate, as characters. Double variables are displayed as floating-
point numbers in scientific notation.
String arguments to the string functions and return values from fgets(),
gets(), and sprintf() are displayed as strings.
You can request that variables be displayed in additional formats, if
appropriate, with these flags:
-o Octal
2/94 - Intergraph Corporation 1
ctrace(1) CLIX ctrace(1)
-x Hexadecimal
-u Unsigned
-e Floating-point
These flags are used only in special circumstances:
-ln 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 flag can hide a bug caused by
use of the = operator in place of the == operator.
-tn Trace n variables per statement instead of the default of 10 (the
maximum number is 20). The Diagnostics section explains when to use
this flag.
-P Run the C preprocessor on the input before tracing it. You can also
use the -D, -I, and -U cpp flags.
These flags are used to tailor the run-time trace package when the traced
program will run in a non-UNIX System environment:
-b Use only basic functions in the trace code, that is, those in ctype,
printf(), and string.
These are usually available even in cross-compilers for microprocessors.
In particular, this flag is needed when the traced program runs under an
operating system that does not have signal(), fflush(), longjmp(), or
setjmpO.
-pstring Change the trace print function from the default of 'printf('.
For example, 'fprintf(stderr,' would send the trace to stderr
output.
-rf 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 flag).
Execution-Time Trace Control
The default operation for ctrace is to trace the entire program file,
unless you use the -f or -v flags to trace specific functions. This 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
2 Intergraph Corporation - 2/94
ctrace(1) CLIX ctrace(1)
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
You can also call these functions from sdb if you compile with the -9
flag. For example, to trace all but lines 7 to 10 in the main function,
enter:
sdb a.out
main:7b ctroff()
main:11b ctron()
r
You can also turn the trace off and on by setting static variable tr_ct_
to 0 and 1, respectively. This is useful if you are using a debugger that
cannot call these functions directly.
EXAMPLE
If the file lc.c contains this 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 these commands and test data:
cc lc.c
a.out
1
(cntl-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
2/94 - Intergraph Corporation 3
ctrace(1) CLIX ctrace(1)
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 (cntl-d) the final output will
be:
/* c == -1 */
10 printf("%d\n", nl);
/* nl == 2 */2
return
Note that the program output displayed 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 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 in line 8 it has the value '\n'. Once your attention is drawn to
this if statement, you will probably realize that you used the assignment
operator (=) in place of the equality operator (==). You can easily miss
this error during code reading.
FILES
/usr/lib/ctrace/runtime.c Run-time trace package
NOTES
4 Intergraph Corporation - 2/94
ctrace(1) CLIX ctrace(1)
The command ctrace does not know about the components of aggregates like
structures, unions, and arrays. It cannot choose a format to display all
the components of an aggregate when an assignment is made to the entire
aggregate. ctrace may choose to display the address of an aggregate or
use the wrong format (for example, 3.149050e-311 for a structure with two
integer members) when displaying the value of an aggregate.
Pointer values are always treated as pointers to character strings.
The loop trace output elimination is done separately for each file of a
multi-file program. This 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.
CAUTIONS
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.
The command ctrace assumes that BADMAG is a preprocessor macro, and that
EOF and NULL are #defined constants. Declaring any of these to be
variables, for example, ``int EOF;'', will cause a syntax error.
DIAGNOSTICS
This section contains diagnostic messages from both ctrace and cc, since
the traced code often gets some cc warning messages. You can get cc error
messages in some rare cases, all of which can be avoided.
ctrace 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 flag 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 flag
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
2/94 - Intergraph Corporation 5
ctrace(1) CLIX ctrace(1)
Split the sequence by removing an else from the middle.
possible syntax error, try -P flag
Use the -P flag to preprocess the ctrace input, along with any
appropriate -D, -I, and -U preprocessor flags. If you still get
the error message, check the Warnings section below.
cc Diagnostics
warning: illegal combination of pointer and integer
warning: statement not reached
warning: size of returns 0
Ignore these messages.
compiler takes size of function
See the ctrace ``possible syntax error'' message above.
yacc stack overflow
See the ctrace ``'if ... else if' sequence too long'' message
above.
out of tree space; simplify expression
Use the -t flag to reduce the number of traced variables per
statement from the default of 10. Ignore the ``ctrace: too many
variables to trace'' warnings you will now get.
redeclaration of signal
Either correct this declaration of signal(), or remove it and
#include <signal.h>.
RELATED INFORMATION
Commands: acc(1), bfs(1), cc(1), tail(1)
Functions: signal(2), ctype(3), fclose(3), printf(3), setjmp(3), string(3)
6 Intergraph Corporation - 2/94