gdb
DebuggerEECS E6870: Speech Recognition
March 16, 2016
What is a debugger, and why use one?
For those of you who are not robots or cyborgs, you will undoubtedly
introduce bugs into your source code at some time or another. One
simple way to debug stuff is to place print
statements everywhere. However, it will make your life much
easier in the long run if you learn how to use a debugger.
A debugger lets you stop the execution of your program at any
point and examine any values you wish, which makes this much
more general and powerful than the print
statement
technique.
Which debugger are we going to use?
The canonical C++ debugger on Linux systems is the GNU
gdb
debugger, a command-line
debugger. While there exist GUI wrappers for gdb
, we have no idea
how to use them because we are old-school.
First, compile the program with debugging information on
This is the default in the Makefile
's supplied by us. (When g++
is invoked, the
flag should be present.)
If you have compiled a program with optimization on (as is sometimes
done in the later parts of labs), then you should run
-g
make clean
and then recompile the program.
Use the
flag with scripts, if available
If a script runs only a single command, then the -dbg
flag can
be used with the script to launch that command in the debugger, e.g.,
-dbg
lab3_p1a.sh -dbg
Otherwise, it's a little more complicated
The
flag is not available for scripts that run multiple commands.
In this case, run the script with the prefix -dbg
to see what commands
are being run, e.g.,
bash -x
bash -x lab3_p2a.sh
Then, select which command you want to debug, and run that command
with the prefix dbg.sh
. For example, to debug the last command
run in the preceding script, you would run
dbg.sh lab3_lm --vocab lab3.syms --train minitrain.txt \
--test test1.txt --delta 0.0001 --n 3 --word_probs p2a.3.probs
The -dbg
flag described in the last section just calls dbg.sh
.
What's going on underneath The normal way to invoke the debugger is as follows:
gdb my_prog
However, you cannot provide command-line arguments for my_prog
when
you do this; instead, they must be supplied as arguments to
the run
command described below. This is inconvenient, so we
supply a wrapper script dbg.sh
that lets you directly invoke the
debugger with command-line arguments. It also sets a couple
of useful breakpoints.
To start your program the first time — Use cont
or c
. (Normally,
one uses the run
command to start execution, but dbg.sh
starts your
program for you and stops it when your main()
function is reached.)
To restart your program — Use run
or r
.
To quit gdb
— Use quit
or q
.
A basic technique in debugging is to stop the execution of your program at strategic points and to examine the values of variables to make sure they are correct. In this section, we discuss different ways of stopping execution.
When an error occurs Your program will automatically stop when
there is a segmentation fault, an assert failure, or an exception.
(For the latter conditions, dbg.sh
sets breakpoints for you.)
Setting breakpoints You can specify a particular line where a program
should stop using the break
or b
command. For example,
b lang_model.C:92
will cause execution to stop whenever line 92 in the file lang_model.C
is hit. Then, you can use the cont
or c
command to continue execution
until a breakpoint is hit.
To skip breakpoints — A numeric argument can be supplied
with the cont
command to skip breakpoints. For example,
c 5
will ignore the first four times a breakpoint is hit and then
stop at the fifth.
To list breakpoints — Use the command
info br
To delete a breakpoint — Use the delete
or d
command. For
example,
d 7
deletes breakpoint number 7.
To advance a single line — Use the step
or s
command, or the next
or n
command. When a function call
is encountered, the former command will step into the function;
i.e., the current line will be the first line of the function body.
With next
, the current line will be the first line after the
function call.
To advance to the end of the current function — Use the
finish
command.
Selecting a stack frame When you examine a local variable, the debugger displays the local variables of the current function. Normally, the current function is set to what you want, but if execution is stopped due to an assert failure or exception, then the current function will be set to the corresponding C++ library function. In this case, what you want to do is set the current function to be the function that called the current function. This can be done with the following command:
up
This tells the debugger to popup one function in the call stack. More generally, the command
where
can be used to print the whole call stack, and the commands up
and
down
can be used to move up and down in the call stack.
Printing variables To print a variable, use the
print
or p
command. Here are example print commands:
p wordCnt
p this->m_n
p m_n
p (*this)->m_n
p (*this)->m_n + 5
As you can see, gdb
can evaluate complex C++ expressions. You
can also examine vectors, e.g.,
p ngramBuf.size()
p ngramBuf[0]
For more information You can use the built-in command
help
or look at a
gdb
tutorial
and there's always Google.
help
. To start gdb
,
type gdb <program>
. Within gdb
,
type run <arguments>
to start the program. Commands
that you should know about include breakpoint
,
print
, cont
, step
, next
,
where
, up
, down
, and finish
.
Don't forget to compile your program with the
flag
(see Section ??).-g