← All 137 books GDB, one concept per page
One concept per page

GDB, one concept per page

Twenty-eight lessons on GDB, one concept per page: what a debugger is and why -g decides everything gdb can see; a first session from gcc -g to run and quit; breakpoints by line, function and file:line; run with arguments and continue; next versus step at every call; finish with the return value and until out of the loop; print, display and the value history of $1, $ and $$; x in count, format and unit; structs, pointers and ptype; backtraces and frames with up and down; watchpoints that stop on the write; conditional stops and command lists; tbreak, ignore and disable; set var to test a theory at the stop; threads; core dumps and post-mortem; a segfault found end to end; TUI mode; batch mode; and a small multi-file program debugged end to end.


Steve Hodgkiss 7 lessons

One concept, one page, one real capture. That's the rhythm.

GDB, one concept per page

Twenty-eight lessons on GDB, one concept per page: what a debugger is and why -g decides everything gdb can see; a first session from gcc -g to run and quit; breakpoints by line, function and file:line; run with arguments and continue; next versus step at every call; finish with the return value and until out of the loop; print, display and the value history of $1, $ and $$; x in count, format and unit; structs, pointers and ptype; backtraces and frames with up and down; watchpoints that stop on the write; conditional stops and command lists; tbreak, ignore and disable; set var to test a theory at the stop; threads; core dumps and post-mortem; a segfault found end to end; TUI mode; batch mode; and a small multi-file program debugged end to end.


Set in Space Grotesk, Inter and JetBrains Mono (SIL Open Font License).

Every fact in this book is as the official source states it, fetched and read during this build: the complete Debugging with GDB manual from sourceware.org (the definition of truth for this book) and the Wikipedia article GNU Debugger. A university gdb tutorial from cs.cmu.edu and the GDB news page were also fetched and cached, but no fact in this book rests on them. No facts are sourced from Reddit, Stack Overflow or vendor blogs. Every command and output pair on every page was run on this machine (GNU gdb 15.1 at /usr/bin/gdb, gcc 13.3.0, Ubuntu 24.04) and confirmed before printing; every run lived in a throwaway directory under a scratch tree, never inside a project or a shared tree. Where this machine's compiler attributes a loop's increment to the loop-header line, so until seems to step back, the page says the behavior out loud: the manual warns of exactly that case. An independent guide, not affiliated with or endorsed by the Free Software Foundation, the GDB maintainers, or the Wikimedia Foundation.

Your purchase is for personal use only. You do not have redistribution rights: please do not share, resell, or republish this book or its pages.

© 2026 Steve Hodgkiss. All rights reserved. Personal use only; no redistribution rights.

Edition 1.0 · stevehodgkiss.net

Contents

Contents


Part 1 · First contact
A first session4
Part 2 · Running and stepping
next versus step5
Part 3 · Examining state
x, memory, formats6
Part 4 · Stopping precisely
backtrace7
Part 5 · Steering the run
set var8
Part 6 · After the crash
A segfault hunt9
Part 7 · A real program
The whole hunt10

Per the GDB manual, you start by naming your program, gdb program, and run starts it under the debugger; start is the plainest stop, setting a temporary breakpoint at the beginning of main. This machine's capture: a whole first session, gcc -g -o prog hello.c then gdb -q ./prog, run printed x is 42 and the inferior exited normally, and start stopped at Temporary breakpoint 1 at 0x1155: file hello.c, line 5.

GDB companion · No. 01
session

A first session

Compile, start, run, quit

five commands, one whole session$ gcc -g -o prog hello.c$ gdb -q ./progReading symbols from ./prog...(gdb) runx is 42exited normally; (gdb) quitstart instead of run:Temporary breakpoint 1at 0x1155: file hello.c,line 5.gdb program is the manual'splainest way to beginrun the whole thing, or start and stop at the first line of main

The whole loop in five lines: gcc -g, then gdb -q ./prog, then run, watch it print, quit. Our capture did exactly that and the program answered x is 42.

start is run with a leash: a temporary breakpoint at the first line of main. Ours read file hello.c, line 5.

-q is politeness only: it hides the banner, never the behavior.

RUN IT THIS WEEK

Type the five-line session yourself, end to end, without copying, until quit lands cleanly.

Per the GDB manual, next continues to the next source line in the current innermost stack frame, executing function calls within the line without stopping, while step goes to the next line to be executed in any subroutine, stepping inside any functions called within the line; both stop at the first instruction of a source line. This machine's captures: three next commands walked main lines 11, 12, 13, 14 of walk.c, stepping over triple(a); a single step at the same point dove into triple (n=5) at walk.c:5.

GDB companion · No. 02
ladder

next versus step

Over the call, or into it

over the call, or into itmain: 11 int a = 5; 12 int b = triple(a); 13 printf("b is %d\n", b);triple(n)next: runs it, stays in mainstep: dives insideboth stop at the first instruction of a source line, the manual saysnext: 11 12 13 14 step: 12 -> triple (n=5) at walk.c:5captured: same breakpoint, one command apartnext executes the call without stopping; step goes to the next line in any subroutine

Same stop, one word apart. next executes the call and stays in main; step goes to the next line in any subroutine, the manual says, so it enters the function.

Our captures: three nexts walked 11, 12, 13, 14; one step at line 12 landed at triple (n=5) at walk.c:5.

Rule of thumb: next through plumbing you trust, step at the exact door you suspect.

RUN IT THIS WEEK

Stop before a function call and walk it twice, once with next and once with step, and say aloud where each lands.

Per the GDB manual, you use the command x, for examine, to examine memory in any of several formats, independently of your program's data types, with x/nfu addr where n is a repeat count, f a display format and u a unit size, and addr an expression for the address. This machine's captures on char name[8] holding hello and int n holding 0x2a: x/s name printed "hello"; x/8xb name printed 0x68 0x65 0x6c 0x6c 0x6f 0x00 and zeros; x/xw, x/dw and x/tw on &n printed 0x0000002a, 42, and binary 101010.

GDB companion · No. 03
memory

x, memory, formats

n count, f format, u unit

one word of memory, five dressesform      what came backx/s name  "hello"x/8xb     0x68 0x65 0x6c...x/xw &n 0x0000002ax/dw &n 42x/tw &n 0...0101010same bytes, chosen dressx is for examine:it reads memory inany of several formats,independently of yourprogram's data types;x/nfu addr: count format unit0x68 0x65 0x6c 0x6c 0x6f 0x00: hello as the machine holds it

x reads memory raw, whatever the compiler thought the bytes meant. One word, 0x2a, dressed three ways: 0x0000002a, 42, 101010.

Its alphabet is x/nfu addr: count, format, unit. Ours: x/s name for the string, x/8xb for the raw bytes, 0x68 0x65 0x6c 0x6c 0x6f 0x00, hello as the machine holds it.

print asks the types; x asks the memory. When a pointer lies, x is the polygraph.

RUN IT THIS WEEK

Print one integer as x, decimal, hex and binary with x, and confirm the dresses agree.

Per the GDB manual, the backtrace command, spelled bt, displays a stack frame for each active subroutine, and bt full adds each frame's local variables. This machine's captures on a four-deep call chain: bt printed #0 innermost at chain.c:6, #1 middle at chain.c:12, #2 outer at chain.c:19 and #3 main at chain.c:25, and bt full showed outer's buf as a char repeated 31 times.

GDB companion · No. 04
stack

backtrace

Every live frame, numbered

the stack, torn down frame by framebt#0 innermost at chain.c:6#1 middle at chain.c:12#2 outer at chain.c:19#3 main at chain.c:25bt full adds locals:buf = '\000' repeats 31the backtrace commanddisplays a stack framefor each activesubroutine, the manualsays: #0 is where itstopped, #3 who began itread a crash bottom-up: deepest frame first, the caller always named

bt tears the stack open: one line per live frame, #0 the deepest, the last number the one that began it all. Ours: innermost, middle, outer, main.

bt full adds each frame's locals; ours showed outer's buf, thirty-one quiet bytes of it.

In a crash, frame 0 is the crime scene and the numbers above it are the getaway route.

RUN IT THIS WEEK

Break inside a three-deep call chain and read the bt aloud bottom frame first, naming each caller.

Per the GDB manual, to alter the value of a variable you evaluate an assignment expression; set is really the same as print except that the value is neither printed nor kept in the value history, and the set variable form avoids clashing with gdb's own set subcommands, the manual's example being set width=47 answered with Invalid syntax in expression. This machine's captures: print limit answered $1 = 10, set var limit = 3 made print answer $2 = 3, and the run completed printing 14 squares up to 3.

GDB companion · No. 05
alter

set var

Test a theory at the stop

change the experiment, not the sourceprint limit -> $1 = 10set var limit = 3print limit -> $2 = 314 squares up to 3set width=47 -> Invalidsyntax, set var dodges itto alter the value of avariable, evaluate anassignment, the manualsays; set is print minusthe echo, and set varavoids command clashesthe change lives in this run only: the binary on disk never moved

Change the program without recompiling: set var limit = 3. Ours printed 14 squares up to 3, one different world.

The manual's trap: set width=47 answers Invalid syntax, because gdb thinks width is its own. set var sidesteps the clash.

The change lives in this run only. Use it to test a theory at the stop; prove it in the source.

RUN IT THIS WEEK

Change one variable at a stop and let the run finish, then predict what a rerun would print without your change.

Per the GDB manual, gdb stops when your program receives a signal such as SIGSEGV and prints the received signal and where it happened, letting you examine the stopped program; per the Wikipedia GNU Debugger article, GDB detects problems in a program while letting it run and allows users to examine program variables and machine registers. This machine's captures: the address-book program died outside gdb with rc=139; run stopped with Program received signal SIGSEGV at book.c:25, the printf reading e->age; print e answered (struct entry *) 0x0; x/s e->name answered Cannot access memory at address 0x0; the guarded rebuild printed no such entry and exited with code 1, and the same clean run under gdb.

GDB companion · No. 06
segfault

A segfault hunt

From rc=139 to the fix

a post-mortem, read off the stopped corpse./prog -> rc=139runProgram received signalSIGSEGV, at book.c:25print e$1 = (struct entry *) 0x0x/s e->name: Cannot accessthe guard is the fix:if (e == NULL) { printf("no such entry\n"); return 1;}rerun: no such entry, rc=1fault line, guilty pointer, null check, clean rerun: four honest moves

The hunt end to end: shell says rc=139, a segfault. Under gdb: Program received signal SIGSEGV, at book.c:25, the line reading e->age.

Ask the state: print e answers (struct entry *) 0x0. The pointer is NULL; the memory read refused, Cannot access memory at address 0x0.

Fix: guard the NULL. Rebuild, rerun: no such entry, exit 1, honest. The whole hunt took four questions.

RUN IT THIS WEEK

Crash a program on purpose, find the guilty pointer with print, and prove the fix with a clean rerun.

Per this book's plan, the whole hunt assembled: a seven-line gdb script against the two-file clamp bug. Every line in the diagram ran on this machine (GNU gdb 15.1): break util.c:5; run; printf with v, lo and hi printed at clamp: v=-5 lo=0 hi=100; bt and frame 1 with info locals answered i = 0 and readings = {-5, 42, 130, 12}; after the fix the rebuilt program printed -5 to 0, 42 to 42, 130 to 100, 12 to 12.

GDB companion · No. 07
capstone

The whole hunt

One script, every concept

one script, every concept, one bug gonebreak util.c:5runprintf "v=%d lo=%d hi=%d"bt; frame 1; info localsv=-5 lo=0 hi=100readings = {-5, 42, 130, 12}the hunt in seven linesthe story this book told:compile with -g, stop onsuspicion, read the stack,print the state, change avalue to test, then fixand rerun to a clean exitbreak, bt, frame, print, set var, fix: the whole book in one walkthrough

Seven lines, one bug: break, run, printf, bt, frame, info locals, continue. The capture names the suspect exactly: v=-5 lo=0 hi=100.

Everything in this book rode along: -g made it legible, file:line crossed the boundary, the stack named both files, the locals handed over the array.

Then the fix, and the rows read 0, 42, 100, 12. If you can run this script cold, the book worked.

RUN IT THIS WEEK

Write the seven-line script for a bug of your own and run it with gdb -batch -x, then fix and rerun to green.

Index

Index


A first session4
A segfault hunt9
backtrace7
next versus step5
set var8
The whole hunt10
x, memory, formats6