GDB: The GNU Debugger
This document is a very basic, brief introduction to GDB, the GNU Debugger. It is our hope that it will give you enough insight into this powerful program for you to be able to utilize it to fix a wide variety of program bugs without needing to consult your teaching staff.
The Basic Operation -- Getting Started
In its most basic incarnation, GDB simply runs over top of your program and watches for a crash. When it does crash, GDB pipes up and tells you at what point in your program it collapsed.
To make it most useful, it is helpful to instruct g++ to add special information to the files it creates to make debugging easier. To do this, simply add the -ggdb parameter to the compilation. So, if you are currently compiling with g++ -o outfile source1.o source2.o, you would then compile with g++ -ggdb -o outfile source1.o source2.o. Nothing changes aside from the addition of the -ggdb after g++.
To launch GDB, simply type at the prompt:
gdb <program name>
where <program name> is the name of your executable file. This will load the debugger with a display like the following:
GDB is free software and you are welcome to distribute copies of it
under certain conditions; type "show copying" to see the conditions.
There is absolutely no warranty for GDB; type "show warranty" for details.
GDB 4.16 (alpha-dec-osf4.0), Copyright 1996 Free Software Foundation, Inc...
(gdb)
The (gdb) is your command prompt. There are a few basic commands that will be of most interest to you:
- help -- The help system. By itself it gives you a list of topics you may select from, or you may add a command word afterwards to get detailed help about that command.
- run -- This will run your program. By itself, standard input and standard output will be the keyboard and the screen, respectively. If you wish to redirect the input or the output, you may do so as you normally would at the shell prompt with the < and > symbols after the run command. For example, run > outfile redirects output to "outfile", run < infile redirects input from "infile", and run < infile > outfile does both. If your program needs arguments, you do not supply them here. See set args below instead. If your program is running already and is stopped because of a crash or breakpoint, this will restart the program from the beginning.
- set args -- This is how you pass arguments to your program. Simply type: set args <arguments>, and they will be passed along when you run the program. These arguments will remain during this debugging session until cleared or reset with another "set args" call. Type "set args" by itself to remove the argument list.
- quit -- This exits from the debugger.
What To Do After A Crash
Those commands should be enough to run your program. If and when it crashes these commands will assist you in diagnosing the problem. You will get a display such as:
Program received signal SIGSEGV, Segmentation fault.
0x8048144 in function() at filename.cc:123
123 some_code_here();
The actual message may vary. Obviously, the function and file names, as well as the code, will depend on your program. The actual error is likely to be a segmentation fault, but could be certain other errors depending on the nature of your problem. The hexidecimal address (the 0x8048144) will almost assuredly be a different number, but it is of no interest to you. The commands of interest are:
- bt -- This will give you a stack trace. It is a listing of lines in the form: #0 0x8048144 in function (parameters) at filename.cc:123, where again, the hex address will be an unimportant number, function will be the function name, parameters will be the parameters used in the invocation of the function, and filename.cc:123 will be the source file and line number of the line in which the program faulted.
#0 will be the innermost call in which the program crashed, and subsequent lines will be the subsequent calling functions. Each function call is known as a "frame". Please note that the innermost frame may sometimes be a system function (such as strlen, strcpy, etc).
If this is the case, chances are you have a problem in one of the outer function calls, such as passing an invalid pointer to a function. It is not the case that there is a problem with system functions if your program crashes in one, and you should look for problems with the data you pass into such functions. Problems like this are quite common when dealing with strings. Look at one of the outer function calls that belongs to you.
- frame -- This sets your frame of reference. From the listing from "bt", this will change your context to the function call in the frame number. For example, frame 2 will put you into frame #2. You can then access variables and other data local to that frame.
- up -- This moves the frame of reference to the calling function. It is identical to calling "frame" with current frame + 1.
- down -- This moves the frame of reference to the function that the current frame called. It is identical to calling "frame" with current frame - 1.
- print -- This allows you to print variables. Simply input an expression after the print command, and you will be given the result. The expression can be just a variable, such as print i, or something more complicated, like print *ptr or print ptr->d.first. Any valid C++ expression is valid here.
- whatis -- This is similar to print, except instead of giving you the value of the expression, this command will tell you the data type returned. This is useful if you are having problems matching data types. Any valid C++ expression is permitted here.
- ptype -- This is similar to whatis, but is only valid for VARIABLES. This will give you the data type of a variable, and if it is an aggregate structure (like a struct or class), will list the internal structure for you. ONLY names of variables in the current frame are valid for this command.
More Advanced Operation -- Breakpoints and Watchpoints
One more very useful feature of debuggers is to instruct them not to wait until the program crashes, but rather tell it to explicitly stop at a certain point in the source code. Breakpoints and watchpoints to exactly this. When one of them is tripped, the program stops, and you are given the (gdb) prompt to use all the commands available to you to print data, change frames of reference, and other such commands just like you can with a crash.
- break -- This sets a breakpoint in the code. A breakpoint is set on a particular line of code and stops every time that line is reached. As a parameter, you can either give it a function name, in which case it will stop at all invocations of that function, or you can give it a filename:line to have it stop at a praticular filename and line number.
- watch -- This sets a watchpoint. This differs from a breakpoint in that it does not stop given a certain location in the code, but rather when the value of an expression changes. When this command is invoked, its parameter is a C++ expression. Whenever the value of the expression changes, the debugger stops and offers you the command prompt. Please note that watchpoints can cause your program to run extremely slow, and you should try to use breakpoints instead whenenver possible. These can be useful, though, for checking with data changes, to see if it changes to something invalid. For example, an expression such as (pointer == NULL) will trip if pointer starts out being NULL and suddenly becomes something non-NULL, or vice versa, as its value will transition from true to false, or vice versa.
- info breakpoints -- This lists all the breakpoints and watchpoints currently set.
- disable -- This command, given a number parameter from the output of "info breakpoints", will disable a given breakpoint or watchpoint.
- continue -- This command will continue execution of the program from after the point at which a breakpoint or watchpoint was tripped. Note that issuing 'run' instead will cause the program to start over from the beginning, not pick up where it left off.
Closing Notes
This tutorial is by far not the entire capability of GDB. It is simply intended to give you enough tools to do basic debugging with this powerful program. You are encouraged to fully explore the 'help' system and learn more about this debugger.
However, for people wanting more, there are a couple options available to you.
- The INFO documentation on GDB. INFO is a GNU extension on the manual page, extending it from a page to practically a whole manual book. You can type "info gdb" on the aITs cluster for this system. Please note that the INFO system uses the Emacs navigation keys, so be sure to familiarize yourself with them before loading this program. As always, the exit key is Ctrl-C followed by Ctrl-X.
- Tasuki Hirata from ISR presented a GDB tutorial some time ago to the Association for Computing Machinery (ACM) at UM. Provided here are his slides (in PostScript format) on debugging. These notes were not written for freshmen computer science students so some parts of the document may be a bit difficult, but it is provided for you to attempt to absorb what you can from it. It is a bit more complete than this tutorial as this tutorial was merely intended as a brief, gentle introduction to this program.
If you find any problems with this tutorial, please report them to Kevin Kane.