# A Quick Tutorial on the gdb Debugger

EECS E6870: Speech Recognition

March 16, 2016

## 1. Introduction

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.

## 2. Launching a Program In The Debugger

First, compile the program with debugging information on This is the default in the Makefile's supplied by us. (When g++ is invoked, the -g 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

make clean
and then recompile the program.

Use the -dbg 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.,

lab3_p1a.sh -dbg

Otherwise, it's a little more complicated The -dbg flag is not available for scripts that run multiple commands. In this case, run the script with the prefix bash -x to see what commands are being run, e.g.,

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.

## 3. Debugging

### 3.1. Basics

• 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.

### 3.2. Stopping Execution

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.

### 3.3. Advancing Execution in a Controlled Manner

• 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.

### 3.4. Examining Variables

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 pop up 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]

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 -g flag (see Section ??).