Table of Contents

gdb

What is GDB?

GDB (the GNU Debugger) lets you inspect and control a running program: pause it at a chosen line, print the value of any variable, walk the call stack, and step through execution one instruction or one source line at a time. It works on compiled C, C++, and Fortran binaries by reading the debug symbols the compiler embedded during compilation.

Without a debugger, diagnosing a crash means reasoning backward from a core dump or scattering printf statements through the code and recompiling after every guess. GDB replaces that loop with direct inspection: you attach to the process at the moment it misbehaves and ask it questions directly, what is this pointer, how did we get here, what did the caller pass in.

GDB requires debug information to be useful. A binary compiled with -O0 -g gives GDB an exact mapping from machine instructions back to source lines and variable names; a binary compiled with -O3 and no -g gives it almost nothing, since the optimiser has already reordered, inlined, and eliminated the very structure GDB would need to explain.

Install

On Debian and Ubuntu:

sudo apt install gdb

On Fedora and RHEL:

sudo dnf install gdb

Compile the target with debug symbols and without optimisation for the most reliable debugging experience:

gcc -O0 -g -o app app.c

Practice

Start GDB with the binary as an argument, set a breakpoint, and run:

gdb ./app
(gdb) break main
(gdb) run
(gdb) next
(gdb) print my_variable
(gdb) continue

break sets a breakpoint by function name or file.c:line. run starts the program, which executes normally until it hits a breakpoint. next steps over the current line (executing any function call in one step); step steps into it. print evaluates a C expression in the current scope, which can be as simple as a variable name or as complex as array[i].field->next.

To debug a crash after the fact, inspect the core dump it left behind:

ulimit -c unlimited          # enable core dumps for this shell
./app                          # crashes, writes core file
gdb ./app core
(gdb) bt                       # backtrace at the moment of the crash

Concepts

Breakpoints and watchpoints

A breakpoint stops execution at a location; a watchpoint stops execution when a value changes, regardless of where in the code that happens. Watchpoints are the tool of choice for “this variable is getting corrupted somewhere and I don't know where”:

(gdb) watch my_struct.count
(gdb) continue

GDB halts the instant my_struct.count changes and reports the old and new value, which pins down the exact line responsible even if it's in code you weren't looking at.

Backtrace and frame navigation

bt prints the call stack, each entry a frame representing one function call still in progress. frame N (or up/down) switches the context GDB uses for print to that frame's locals and arguments, which is how you inspect a caller's state after a crash deep in a callee:

(gdb) bt
#0  vector_push (v=0x..., x=42) at vector.c:31
#1  process_item (item=0x...) at process.c:88
#2  main () at main.c:15
(gdb) frame 1
(gdb) print item->id

Conditional breakpoints

A breakpoint can carry a condition, useful for a bug that only shows up on, say, the 10,000th loop iteration:

(gdb) break process_item if i == 9999

Without the condition, hitting continue 9999 times by hand would be impractical. GDB evaluates the condition every time the breakpoint location is reached and only actually stops when it's true.

TUI mode

gdb -tui (or Ctrl-X Ctrl-A inside a running session) splits the terminal into a source-code pane and a command pane, so stepping through code shows the current line highlighted in context rather than requiring a separate list command after every step.

gdb -tui ./app

Attaching to a running process

GDB can attach to an already-running process by PID, which is the only option once a program is already hung or stuck rather than freshly launched:

gdb -p $(pgrep app)

This is common for diagnosing a deadlock: attach, then bt on each thread with thread apply all bt to see exactly where every thread is blocked.