Using a debugger allows you to investigate the state of your programme. If you’re working in C or C++, familiarity with a debugger like GDB is more or less essential.
GDB is the GNU debugger - it is a tool that allows you to see what is going on “inside” your target programme while it is executing - or what a programme was doing at the moment it crashed.
To use GDB, compile with debugging symbols: these are extra pieces of data that help the tool determine the layout of code and data in memory.
-g option instructs
gcc to compile with debugging symbols. Use
-ggdb3 for the maximum amount of debugging information. If compiling in multiple steps, include
-ggdb3 at each step.
Once the programme has been compiled with debugging symbols, run
gdb from the command line, providing the name of your executable as the sole argument:
gdb ./my-prog. If your programme requires arguments, you don’t enter them at this stage.
Commands: Moving Through the Programme
r: Run the programme, or possibly restart it. The programme will run until it encounters a condition that causes it to stop - a crash, breakpoint etc.
start: Begin (or restart) the programme. Similar to
start is the equivalent of setting a temporary breakpoint at the beginning of the main procedure. The
start command stops the programme (e.g. to accept more commands) as soon as execution enters the main function -
main() in C and C++.
s: Advance the programme one step -
step will go into called functions.
n: Advance the program one line. Unlike step, if the current line of code is a function call, GDB will execute the entire called function without jumping into the function.
Hit enter without entering a command to repeat the last command.
Command Line Arguments
To pass command line arguments, you can either add them after the
r) command (e.g.
r someArg anotherArg), or you can use
set args to set command line arguments.
display commands allow you to see what value an expression evaluates to.
p: Evaluates an expression and prints the result. Print a variable x:
p x to show the value of
x at the current position in the programme.
If the expression has side-effects they will affect the state of the program - if you do
p x = 3, x is set to 3 and printed.
/x: Integer in hexadecimal format
/d: Integer in signed decimal
/u: Integer in unsigned decimal
/o: Integer in octal
/t: Integer in binary (“t” == “two”)
/a: Print as an address
E.g. print variable
i in hex format:
See here for more options.
When you print the value of an expression, GDB remembers the value in internal variables which are named
$2 etc. Gdb shows the internal variable when it prints the value e.g.,
$1 = 42.
$ variables can be used in subsequent expressions.
Print from Array
You can print multiple elements from an array - put
@number after an lvalue name and GDB prints
number values starting at that index.
A is an array,
p A@5 will print the first 5 elements.
Print all elements in array
A of length
disp: Automatically display certain expressions each time GDB stops at a breakpoint or after a step. To display the value of
i at each breakpoint:
Investigating the State of Your Program
Inspect Stack Frames
GDB allows you to inspect the current set of stack frames and move up and down within them. The
bt) command lists all of the stack frames with the current one on top, and main on the bottom - showing the function calls that lead up to the current position. The
backtrace also shows the line where each call was made.
Gdb uses the variables in the current scope when executing the
down command, which move scope up and down the stack.
If the programme stops in a failed assert GDB will stop deep inside the C library - in the code that handles assert. The code under examination is likely to be a number of stack frames up. Use the
up command a few times until GDB enters the appropriate frame.
info command provides information about various aspects of the programme. This command has various subcommands:
info framedescribes the memory layout of the current frame
info typesdescribes the types that are in the current program
info binformation about breakpoints
info options - use
help info for more information.
To kill GDB and restart a fresh debugging session without restarting GDB:
kill) and enter ‘y’.
Next and Step
Start the programme with
start, then step through execution line by line.
s) commands advance the state of the program line-by-line.
A breakpoint instructs GDB to stop execution whenever the program reaches a particular line.
# Breakpoint inside function main() - break inserted just after opening curly brace: b main Breakpoint 1 at 0x4007de: file main.c, line 6. # Breakpoint in file main.c on line 42: b main.c:42 Breakpoint 2 at 0x4009b5: file main.c, line 43.
Breakpoints are set with the
b) command, followed by either a line number or a function name (meaning to set the breakpoint at the start of that function).
When you set a breakpoint, GDB assigns it an ID number.
The programme runs (or continues if already started) until the breakpoint. When the breakpoint is encountered, GDB pauses execution and allows you to inspect the state of the programme at this point.
You can enter
c to continue from the breakpoint, which jumps to the next breakpoint. You can also use
s to step through the programme from this point.
By default, breakpoints are unconditional. GDB will stop the program and give you control anytime it reaches the appropriate line.
Conditional breakpoints are very useful for looking inside loops and recursive reoutines.
Break on line 7 if
i is as specified:
(gdb) break 7 if i==2
Show info on currently set breakpoints:
info b Num Type Disp Enb Address What 1 breakpoint keep y 0x00000000004007de in main at main.c:6 2 breakpoint keep y 0x00000000004009b5 in main at main.c:43
Delete all Breakpoints
d and enter ‘y’ to confirm.
Delete Specific Breakpoint
Get the ID using
info b then
d x to delete breakpoint with id x.
Disable all Breakpoints
disable with no arguments to disable all breakpoints. To enable, enter
enable x where
x is the ID of the breakpoint in question.
Disable Specific Breakpoints
disable x # disable multiple, space separated: disable x y
Save and Reload Breakpoints
Save current breakpoints into a file
save breakpoints bp-store.txt
bt after programme interruption to see a backtrace - a list of function calls, representing the call stack. The top line is the frame that was current when the programme was interrupted.
frame command to inspect a specified frame.
A watchpoint stops execution when the value of an expression changes. The simplest use is to watch the value of a single variable - the command
watch i causes a break whenever the value of
i changes, printing the old & new values.
Watchpoints can be useful when debugging pointer-related issues.
If the alias (variable) associated with the watchpoint goes out of scope before changing, you can find the relevant GDB variable (e.g.
$1) by using
More info on watchpoints, or enter
info gdb and search for
When a programme receives a signal, GDB will stop the programme and give you control.
Indicates a segmentation fault. The programme has attempted to access a restricted area of memory.
Execution stops the programme on the line where the segfault happened. You can inspect the state of the program (printing out variables) to see what went wrong.
abort() or fails an assert. GDB leaves you in control of the programme at the point where assert caused the abort. You may need to move through frames to get back into your own code to debug the fault.
Programme is interrupted - e.g. by the user pressing Control-c. If the programme is getting stuck in an infinite loop, run it in GDB and press Control-c. Once execution has halted use
bt to view a backtrace. To examine a particular frame, use the
frame command, e.g.
(gdb) f 4 to inspect frame 4.
comments powered by Disqus