Adapted from http://www.cs.princeton.edu/~benjasik/gdb/gdbtut.html
A debugger is a program that runs other programs, allowing the user to exercise control over these programs, and to examine variables when problems arise. The most popular debugger for UNIX systems is gdb, the GNU debugger. gdb has tons of features, however, you only need to use a few for it to be useful. There is complete documentation for gdb online, or you can read the man page (type "man gdb" at the unix command prompt), and the quick reference card is very handy.
Basic features of a debugger
When you are execute a program that does not behave as you like, you need some way to step through you logic other than just looking at your code. Some things you want to know are:
g++ -g lexdriver.cppwhich will create the executable (a.out by default). If you are using the provided makefile, just change CFLAGS = -o to CFLAGS = -g -o . (Note that -g must precede the -o option, which specifies the name for the executable.)
Once your executable has been generated by the compiler, it is run under the control of gdb by typing
gdb a.outor, if for example you have generated an executable with the name tokenize, say
gdb tokenizeThis starts up the text interface to the debugger. It's much easier to use gdb under emacs, but we'll use this interface to describe the commands.
Starts your program as if you had typed
a.out command-line-argumentsor you can do the following
a.out < somefileto pipe a file as standard input to your program.
Creates a breakpoint; the program will halt when it gets there. The most common breakpoints are at the beginnings of functions, as in
(gdb) break get_next_tokenThe command break main stops at the beginning of execution. You can also set breakpoints at a particular line in a source file:
Breakpoint 2 at 0x2290: file get_next_token.cpp, line 20
(gdb) break 20When you run your program and it hits a breakpoint, you'll get a message and prompt like this:
Breakpoint 1 at 0x2290: file lexdriver.cpp, line 20
Breakpoint 1, main (argc=2, argv=0xffbef8ac) at lexdriver.cpp:11
(gdb)
In emacs, you may also use C-c C-b to set a breakpoint at the current point in the program (the line you have stepped to, for example) or you can move to the line at which you wish to set a breakpoint, and type C-x SPC (Control-X followed by a space).
Removes breakpoint number N. Leave off N to remove all breakpoints. info break gives info about each breakpoint
Provides a brief description of a GDB command or topic. Plain help lists the possible topics
Executes the current line of the program and stops on the next statement to be executed
Like step, however, if the current line of the program contains a function call, it executes the function and stops at the next line.
Keeps doing nexts, without stepping, until reaching the end of the current function
Continues regular execution of the program until a breakpoint is hit or the program stops
Reloads the debugging info. You need to do this if you are debugging under emacs, and you recompile in a different executable. You MUST tell gdb to load the new file, or else you will keep trying to debug the old program, and this will drive you crazy
Produces a backtrace - the chain of function calls that brought the program to its current place. The command backtrace is equivalent
prints the value of E in the current framein the program, where E is a C expression (usually just a variable). display is similar, except every time you execute a next or step, it will print out the expression based on the new variable values
Leave GDB. If you are running gdb under emacs,
C-x 0(that's a zero, not an o) will get you just your code back
To begin, invoke emacs and edit the source program you want to debug. The easiest way to do this is to go into the directory where the files comprising your program reside and invoke emacs with the file name of the main module--e.g., emacs lexdriver.cpp. If you are using the makefile, before doing anything else be sure you have edited the makefile to specify
CFLAGS = -g -o
(making sure the -g comes before the -o).
To compile the program, hit the f5 key, or enter M-x compile. You will get the prompt
Compile command: make -k
You can just hit return unless you want to specify your own compile command, in which case you can use the Delete key (or Backspace key, on some terminals) to erase the make -k and replace it with, for example, g++ -g -o tokenize lexdriver.cpp get_next_token.cpp char_stream.cpp error.cpp. You may get a prompt asking to save the file ; if you answer "y" emacs will save the file before compiling it.
When the program compiles, emacs creates a new buffer for the compile. Eventually, that new buffer will include a "Compilation finished" message, and will display any syntax errors that were found. If there are any such errors, you can keep typing
C-x `
(C-x and then a backward apostrophe), and emacs will automatically go to the buffer for the source file and position the cursor at the source of the error; this is a big convenience.
Now invoke gdb using the command M-x gdb. Or, to use the ddd graphical interface (recommended), type M-x gdb, then at the prompt change the command to ddd --gdb. If you use gdb without ddd, emacs will create a new buffer for gdb, and you are now ready to enter gdb commands. The first command to enter is
file tokenize
in order to provide gdb with the symbol table for the last compilation that produced the executable named tokenize. Now you can set one or more breakpoints, and then say
run lextest.dat
which runs the tokenize executable with the input file lextest.dat.
When gdb stops at a breakpoint, emacs will take
the file and line number reported by gdb and display the file
contents in a second buffer below the gdb buffer, with the point of the breakpoint marked with =>. As you step
through a program, emacs will follow your progress in the source file. For example, if you give gdb an "n" (next) command ,
it will execute that statement and the "=>" marker will
then advance to the next line in the source file.
You can see the content of any variable at any time
with the
Using ddd is much simpler. GNU has a good
overview and summary.