GDB Quick Start Guide
GDB (GNU debugger) can pause the execution of a running program and let
you examine/take control of its memory. It's probably one of the most
powerful tools that can help you nail down the exact cause of a problem
with your program. For most of the time it works like having printf
s
in your code but it's much more extensible and efficient. In the
examples below, a "$
" prompt means a command is typed to a operating
system shell, and a "#
" prompt means a command is typed to the GDB
command prompt.
Preparation
Before running gdb
, please be sure that the program is compiled with
the -g
compiler flag. This flag tells the compiler to insert "debug
symbols" into the executable so that you can refer to the variables by
the same names as you declared them in C.
Launch a Program in GDB
To debug a program, we must launch it with GDB.
$ gdb ./program
If the program requires command line arguments, please take a look at the Programs with Command Line Arguments section (on the same page). After GDB successfully loads the program we will be taken to the GDB command prompt. We can interact with GDB through a set of GDB commands. Type a command and press return to execute the command.
Useful GDB Commands
break
: Insert a breakpoint. A breakpoint is a special location in
the program, and GDB will pause the execution of the program once this
location is reached. A breakpoint is identified by a file name and a
line number (like hello_world.c:10
, meaning the 10th line in file
hello_world.c
). Example:
# break hello_world.c:10
run
: This command tells the GDB to start executing the program
from the very beginning. The program will keep executing until it hits a
"breakpoint" set with the break
command above.
next
: Only works when the program is "paused" because of a
breakpoint. It executes the next statement in the program and pause the
program again. This behavior is also known as "step over", which means
if the next statement to execute is a function call, it will "step over"
the function call and will only pause the program again after the
function call returns.
step
: Similar to "next"
, but it works in a "step into" fashion.
If the next statement to execute is a function call, step
will pause
the program at the first executable statement INSIDE that function.
finish
: This command continues the currently executing function,
and pause the program again right after the function returns. It's
particularly useful when you inadvertly step
ped into a function that
you don't actually care about (like printf
).
continue
: Continue executing a paused program. It works similarly
to run
in the sense that the program will only stop once another
breakpoint is hit, but it doesn't restart the program.
backtrace
: When a program is paused or encounted an error, this
command can be used to inspect the most recent call stack. It will give
you information about which code called a certain function - it's
particularly useful when you have problems like a segmentation fault.
print
: This is the ultimate command! Pretty much everything else
we do in GDB is to set things up so we can use print
to print out a
variable value. The print
command accepts variable names (subject to
scopes), or even plain memory locations. It can also be used to execute
a function and print out the return value. Example:
// int count = 0;
# print count
up/down
: This pair of commands help you navigate between different
function frames in the call stack. For example, you want to access a
local variable in the caller's frame of the current executing function,
which is out-of-scope, you cannot direct access it via print
by
referring to it using the variable name. What you can do instead is to
go up one level in the call stack using up
and then print the
variable. It's often used in conjunction with the backtrace
command so
that you know which function you are looking at/going to.
info breakpoints
: This command gives you a list of breakpoints
that are currently set in the program. (There are many other useful
info
commands; see notes)
disable/enable
: This pair of command is used to manage
breakpoints. You can have a lot of breakpoints in a program and that's
fine, just disable the ones you don't need, and re-enable them when you
need them again! You should refer to breakpoints using the breakpoint
number returned by the "info breakpoints"
command mentioned above.
Example:
# disable 2
Using the TUI
GDB provides a useful feature called the TUI (terminal user interface)
that allows you to see code and/or assembly alongside the debugging
console. This prevents you from having to list
frequently to find
where you are. To activate the TUI, press either Ctrl + X 2
(control + X, followed by 2) to view both source and assembly, or
Ctrl + X 1
to view just source. To switch between views, use
Ctrl + X O
.
Programs with Command Line Arguments
There are two ways to launch a program with command line arguments.
1. To use the --args
argument when launching GDB in shell:
$ gdb --args arg1 arg2 ./program
2. To attach arguments to the "run" command in GDB command prompt:
# run arg1 arg2
Notes
- Many of these commands have short-hand representations (in most cases
it's just the first letter of the full command, like
b
forbreak
, etc.). - Once you feel comfortable with GDB, it's good to know some more "advanced" commands that may help you debug your code later in this course. Many of those commands operate at a lower level, interacting with machine instructions and plain memory locations. This list contains many such commands.