Debugging with gdb
A Quick Reference
gdb is a text-based program which allows you to “see” what your program is doing. It runs your program in a “protected” environment, in which gdb catches all “signals” (like refernces to illegal memory locations), allows you to stop execution in a controlled way, see the values of variables, either continue execution, or restart the program from a “fresh” copy.
gdb is intended for C, C++ and FORTRAN programs. To use gdb effectively, you should compile all programs using the “-g” option, to include program symbolic names in the compiler output. When this is done, gdb will be able to list lines in your source program, find the start of each procedure or method in your program, and find and print program variables. gdb will also know the declared type of each variable, and can print the variables in a useful format, based on this knowledge.
When you start gdb, it prints the prompt (gdb) and waits for you to type a command. The commands you type allow you to manually control what gdb does, step by step. The commands I find most helpful are:
help Gives you information about how to use commands, and what they do. Use “help command” to get details about command.
break Used to tell gdb to stop execution at a specific location in the program, say at the entrance to a procedure, or the start of a specific line in a procedure. Can be made “conditional”, so it only stops when some expression evaluates TRUE.
delete Deletes a break-point, whose number is its argument. (Abbreviation: del )
cond Makes a breakpoint “conditional”. “cond 3 x>10” causes breakpoint 3 to become conditional, so it only stops if x>10.
run Starts executing your program at full speed. If specified, gives command line arguments to the program. Otherwise, uses the previously specified arguments.
^C (The “interrupt” key). Used to stop your program in its tracks, so you can see where it is executing, and what the values of its variables are.
next Executes one line of C code and stops again in gdb, executing through subroutine calls on that line. Use step to step into subroutines.
where Shows the nest of procedures currently in
execution, giving the arguments passed to each of them. You can examine the variables local to the
current (deepest) of these procedures, or you can change the procedure context
by using commands up and down.
continue Continues execution after gdb stops. (Abbreviation: c )
print Prints the value of an expression, using
the current values of any variables mentioned in it. The format of the output can be controlled, by adding a special
first argument:
/x Hexadecimal
/f Float
display Like print, but is remembered, and executes every time gdb stops.
list Lists several lines in your program around the specified line, or procedure entrance. With no argument, continues listing from the last listed line; with an argument of “-“, lists the lines preceding the last set of lines listed.
Using gdb allows you to play detective, investigate what your program was doing, and why, just before it gets into trouble. For example, if your program fails an assertion on line 113 of procedure Golum, I would execute gdb on the program, and at the prompt type:
list Golum
list 113
break 113
cond <breakpoint number> <negated ASSERT condition>
run <arguments>
Assuming the arguments to the program and any files it reads are unchanged, the program should attempt to execute the ASSERT, but this time will hit the breakpoint instead, and (if the ASSERT fails) will send control to gdb rather than aborting the execution. Now gdb will print a (gdb) prompt, and allow you to enter new commands, such as
where (to find out what called the method which failed the ASSERT, and what called it, etc.)
print (to determine what the “state” of the
program is, and possibly identify variables
whose values are “suspicious”)
Once you’ve discovered values that aren’t correct, that could cause the symptom, you must think about what part of the program might have computed the erroneous values. You can put breakpoints on the statements that compute suspicious variable values, and re-execute the program, using “run”, with no arguments. Or just use breakpoints placed at the starts of various “stages” of the program, stop at each of them, and investigate variable values at that time.