One use for dbx or gdb is to analyze a core file from a program that has crashed.
A second use is to trace execution of a program.
The compiler you use determines which debugger you should use. If
you use the GNU C compiler (gcc) then you should use the gdb
debugger. Generally the dbx debugger is used for all other
compilers and most notably the Sun C compiler. (On the AIX machines,
only dbx is available, however on Thetis and Valdes
gdb is available.)
abort();
or if an error interrupt occurs. Most computers will generate
an interrupt when the program attempts to access a memory location
outside the region it has been allocated, or for dividing by zero,
or for floating-point overflow ... The exact list of errors that
generate interrupts depends on the computer and on the system
software. (The IBM AIX workstations do not, for example, catch
divide by zero errors.)
% myprog
Segmentation fault (core dumped)
% ls -l
-rw-r--r-- 1 nigelh csciperm 23979 Jan 31 09:36 core
-rwxr-xr-x 1 nigelh csciperm 4620 Jan 31 09:25 myprog
-rw-r--r-- 1 nigelh csciperm 163 Jan 31 09:16 myprog.c
limit coredumpsize 50
will prevent a core file from growing larger than 50KB. It is quite possible that your `.login' file or `.cshrc' file (which contain commands to be executed when the shell is started up) contains the command:
limit coredumpsize 0
To be able to debug a crashed program with dbx or gdb, you need the whole core file. If you execute the command
unlimit coredumpsize
and then re-run the program that crashes, you will obtain the
complete core file. A better suggestion is to edit your .cshrc
file and remove the line which limits the coredumpsize.
% cc -g -o buggy buggy.c
If you have a multifile program, composed from one.c two.c ..., then all cc invocations need the -g flag. E.g.
% cc -c -g one.c
% cc -c -g two.c
...
% cc -g -o bigBuggy one.o two.o ...
% dbx buggy core
or
% gdb buggy core
to start dbx or gdb. It will read the two
files, report the line where the program stopped, and then wait
for you to enter subcommands.
The output that dbx or gdb produces when it
starts up should look something like this:
Type 'help' for help.
reading symbolic information ...
[using memory image in core]
Segmentation fault in calcSubr at line 7
7 A[n] = 0;
Note that the output tells you the name of the function that
was being executed when the program crashed, the source code line
number, and a listing of exactly that line.
(An experienced C programmer would immediately guess from that
listing of the line that variable n is probably out of
range. Note that n being just out of range is
unlikely to cause the program to crash. The location
A[-1], for example, is probably still within the
region of memory belonging to the program.)
could not read "buggy.c"
instead of displaying the line of source code.
The AIX version of dbx therefore has an extra option that
tells it the name of a directory to check when looking for source
code files. This option may be used several times if there are
several directories to check. For example, if the program
buggy has been created from source code in subdirectories
named Module1 and Module2, we should invoke dbx with the
command:
dbx -I Module1 -I Module2 buggy core
(That option letter is an upper-case i.)
Alternatively, you give those directory names to dbx with
the use command (see below).
|
where |
shows active functions |
|
dump |
dumps all variables |
|
print expr |
evaluates and prints an expression |
|
up |
go up to parent function |
|
down |
go down to child function |
|
list functionName |
display 10 lines of source code of the named function |
|
list |
display another 10 lines of code |
|
func functionName |
prepare to examine the named function |
|
file fileName |
prepare to examine the named source code file |
|
whatis variableName |
shows the datatype of the variable |
|
which variableName |
to ask which variable of this name is visible here |
|
whereis variableName |
asks where all the variables of this name are located |
|
use directory list |
if you forgot to provide the -I option when you started up dbx, you can instead list the directory names in the use command. |
|
help |
general help facility |
|
help command |
display help info about a command |
|
quit |
exit from dbx or gdb |
use . Module1 Module2
This tells dbx or gdb to check the current
directory and the two specified subdirectories for source code
files.
alias p print
alias l list
...
The next time you use dbx or gdb, you can
then use the command p as a synonym for print,
and so on.
print A[n+1]
prints the value of the expression A[n+1] using the current value of the variable n and the current contents of the array A. You can print the values of several expressions simultaneously. E.g.
print n, A[n+1]
print p, p->next, p->next->next
to show the first three elements in a linked list (whose head
pointer is p, and where the link field in each element is named
next).
print A@50
where A is the name of the array and A has 50 elements. And
that's all there is to it.
For dbx, it is necessary to use a special notation that
works for displaying the contents of any region of memory.
To use this notation, you must specify the starting and ending
addresses of the desired region of memory, and the format to use
when printing the memory contents.
For example, suppose that we wish to print the contents of the
array named A. First, you might use the dbx command:
whatis A
The answer might come back looking like:
int A[50];
(I.e. dbx has located the declaration of A in the source code and displays it for you.) Using your general knowledge of the computer and of C, you should know that int values require 4 bytes each. If you do not know this, you could ask dbx by using the command
print sizeof(int)
and dbx will print 4 as the value of that C
expression.
Now you can deduce that the array A is 200 bytes in size and you
might ask dbx to print out the contents of memory for A
as follows:
&A,&A+200/D
The command is written as: address,address/format. The start
address is simply &A (the C notation for the address
of an object). The end address is &A+200 (i.e.
dbx accepts an expression as the address). The format is
D. The code letter D means 4-byte decimal number.
The most useful format code letters are as follows:
- c
- one-byte ASCII character
- d
- 2-byte decimal integer
- D
- 4-byte decimal integer
- f
- 4-byte floating-point number
- g
- 8-byte floating-point number
- h
- one-byte hexadecimal number
- s
- a character string terminated by a null byte
- x
- 2-byte hexadecimal number
- X
- 4-byte hexadecimal number
&A/50D
The number 50, here, is a repetition factor for the format code
that follows.
&main/20i
The format code i means machine instruction.
% dbx buggy
If your program was created from source code in other directories, you could supply the -I flag for each such directory. E.g.
% dbx -I Module1 -I Module2 buggy
Alternatively, you can enter the use subcommand of
dbx (as explained above).
|
trace funcName |
ask for all calls to and returns from the function to generate trace output |
|
trace variableName |
ask for all assignments to the specified variable to generate trace output |
|
stop in functionName |
cause execution to halt if control enters the named function |
|
stop variableName |
cause execution to halt at any assignment to the specified variable |
|
stop at lineNumber |
stop if control reaches the specified line number |
(with the appropriate fileName) before using the stop at command. For example:
file calcSubr.c
stop at 27
run
If the program requires command line arguments, you can supply those, as in
run -d myfile
If it requires file redirections, then these can be supplied too:
run < inputFile
(I.e., invoking the program is the same as running the program
from the shell command line, except that the program name is
replaced by the word run.)
cont
rerun
(Again, arguments may be supplied. If you fail to supply
arguments, the same ones as were used on the earlier run command
will be re-used.)
step
causes one line of the program to be executed, and then the program halts again. If you would like to step through 10 statements and stop again, the command would be
step 10
next
The difference is that next causes any functions
called inside the current statement to be fully executed. (The
step subcommand would cause control to stop inside the
function.)
Again, the command form
next 10
is available.
stop at 37 if i<0
will cause control to stop just before executing line 37 in the
current source code file if variable i happens to be less
than zero at this point.
assign i = 27
which stores 27 into variable i. Values of any simple C datatype can be assigned. Here are examples:
assign ch = '*'
assign f = 3.5e-5
assign s = "some string value"
&func/20i
form of instruction.)
gdb has the same functionality as dbx, however it is more popular since it works for a better compiler (gcc) and its commands are less verbose. For any command you can just enter the start of the command name to remove any ambiguity and the debugger will figure out what you mean. Example p will mean print. Some basic equivalent commands in gdb are:
|
break file:line |
add a breakpoint at a given file and line number. |
|
break func |
add a breakpoint at the start of function func. |
|
next |
Execute the next statement. If it is a function call then stop after executing the function. |
|
step |
Execute the next statement. If it is a function call then enter the function and stop. |
|
backtrace |
List the program stack. A synonym for this command is bt. |
|
frame num |
Go to the stack frame number num. |
|
print var |
Print the value of variable var. |
|
list |
display current lines of code. |
For either gdb or dbx you can get additional
information by using the command