Introduction to the gdb debugger


Why bother?

To improve our debugging skills. The better we can debug, the faster we can program and the less frustration we experience along the way.

One means of debugging is to use print statements. Some argue that using a debugger is more convenient. For example [2b]:

What do debuggers let you do?

A debugger is a program that runs other programs, allowing its user to exercise some degree of control over these programs, and to examine them when things go amiss [1a].

In particular, debuggers let you [3]:

Getting started with gdb

When you compile, include a -g flag. Following that, you can execute gdb on the executable created. For example:

    Shell> g++ -g hello.c -o myprog
    Shell> gdb myprog

Common gdb commands

The following table is based on [1b]. It should be noted that although gdb supports a wide variety of commands, learning only a few can go a long way to help with debugging.

Essential Commands
run command-line-arguments
  • start your program [with command-line-arguments]
  • gdb remembers the arguments you pass, and plain run thereafter will restart your program from the top with those arguments
killthe kill command terminates the currently running program so you can start debugging at the beginning. (You can also just re-type run and it will prompt to start again from the begining)
whereproduce a backtrace -- the chain of function calls that brought the program to its current place. The commands bt and backtrace are synonyms
quitquit the debugger
helplist help topics
help commanddescribe command
Listing Source Code
listshow the next ten lines of source code
list -show previous ten lines
list [file:]numshow the source surrounding line number num
list [file:]functionshow the source surrounding the beginning of the function
list f,lshow the source from line f to line l
Breakpoints
break [file:]numset breakpoint at line number [in file]
break [file:]functionset breakpoint at start of function [in file]
delete [num]delete the breakpoint numbered num
continue [count]Used to restart execution of the program after a breakpoint. If count is specified, ignore this breakpoint next count times
disable [num]disables the breakpoint numbered num. If no argument is used, all breakpoints are disabled
enable [num]enabbles the breakpoint numbered num. If no argument is used, all breakpoints are enabled
info breakpointsprint out all of your current breakpoints
Execution Control
step [count]
  • Steps can only be used after the program has been halted for some reason, either due to a user-defined break or a seg fault, etc.
  • If count is specified then it tells how many steps to take at once. By default, step advances through one line of source code
next [count]Like step, except that function calls are treated different:
  • next will execute the entire function and stop at the program line after the function call
  • step will stop at the first line in the function
finishKeeps doing nexts, without stopping, until reaching the end of the current function
Displaying Variables
print [expr]
  • view the value of a variable expr at the time of a break/error
  • expr can also be a C++ expression
display exprshow the value of expr each time the program stops
undisplay numremove number(s) num from list of automatically displayed expressions
info displayshow numbered list of all automatic display expressions

Example of a gdb session

The following is an example session, recorded using the script command:

I used the cat command to introduce the program file we will work with.

Ok, this executable has a bug somethere. We invoke gdb to help us find it..

The above is the introductory message that gdb gives us. First off, we try running the program with some arguments

Now we want to pinpoint where the segmentation fault occurred, so we use the where command

Aha! main called processSomething which called sprintf and then died somewhere thereafter. Lets take a look at the function processSomething..

Ok, now the problem is more evident. We are trying to write to a string buf that has not yet been allocated any memory space.

In a separate window we invoke our favorite editor. We replace char *buf; with char buf[80];. In a separate window again we compile our program again. Note that we don't have to leave gdb during this time. Now that our fix is done, we verify that it solves the problem..

Alright. Mission accomplished. That wasn't so bad, eh?

References

  1. University of Michigan
    1. gdb tutorial (postscript file) by P. N. Hilfinger
    2. gdb reference Card (postscript file)
    3. gdb summary
  2. University of California at Davis
    1. gdb tutorial
    2. Guide to Faster, Less Frustrating Debugging, by Norman Matloff
  3. gdb tutorial (slides) at University of Cincinnati
  4. Reference on gdb, by Richard Stallman and Roland Pesch