5.3.15 · D2Build Systems & Toolchain

Visual walkthrough — GDB debugging — breakpoints, watchpoints, step, next, backtrace

2,056 words9 min readBack to topic

This is the visual companion to the GDB debugging note. We assume you know nothing but "a program is a list of instructions the CPU runs one after another."


Step 1 — What "running normally" even means

WHY we start here: before we can measure extra cost, we must measure the baseline — the time when GDB is doing nothing special. Every symbol in the final formula is a comparison against this baseline, so it must be pinned down first.

PICTURE: Look at the green bar below. It is one program run, chopped into equal slices — each slice is one source line of your code. The whole green bar takes total time .

Figure — GDB debugging — breakpoints, watchpoints, step, next, backtrace

So the cost of one line, on average, is the green bar's length divided into pieces: . Hold onto that number — it's tiny, and its tininess is the whole plot.


Step 2 — What a watchpoint is asking the CPU to do

WHY this matters: a breakpoint knows its address, so GDB pokes one trap byte and walks away (see Parent Step: byte substitution). A watchpoint can't do that — the variable might be modified by line 3, or line 300, or a line in a library. GDB is forced to check after every single line.

PICTURE: the red magnifying glass sits between every pair of green slices. That gap is the check GDB inserts. There are slices, so there are checks.

Figure — GDB debugging — breakpoints, watchpoints, step, next, backtrace

The red glass is not free. Each one costs a fixed amount of time. We give it a name in the next step.


Step 3 — Naming the cost of one check:

WHY a single letter: the three sub-costs always happen together, once per line, so we don't need three symbols — we need one. Collapsing them into keeps the algebra honest and the picture clean.

PICTURE: we zoom into a single red glass and unfold it into its trap → read → compare pieces. Their total width is labelled .

Figure — GDB debugging — breakpoints, watchpoints, step, next, backtrace

Step 4 — Adding up all the extra work

WHY multiply: this is the definition of "the same fixed cost, repeated." identical red glasses laid end to end have total length . No calculus needed — repetition is multiplication.

PICTURE: the green baseline bar, now with a red bar of length bolted onto its end. The red bar is the pile of all the traps.

Figure — GDB debugging — breakpoints, watchpoints, step, next, backtrace

Step 5 — Turning time into a slowdown ratio

WHY divide, not subtract: subtracting gives you seconds of delay (), but a 100 s delay is trivial on a 3-hour job and catastrophic on a 1 s job. Dividing by makes the answer scale-free — it tells you the factor, which is what "10× slower" means in everyday speech.

PICTURE: we stack the red-plus-green bar on top of the plain green bar and read off how many times taller it is.

Figure — GDB debugging — breakpoints, watchpoints, step, next, backtrace

Step 6 — Plug in numbers (forecast → verify)

WHY these numbers: they're deliberately "normal" — a 1-second program running a hundred million lines — so the shocking answer isn't a trick of exotic inputs.

PICTURE: the same stacked bars, now with real tick values, so you see 100 s of red towering over 1 s of green.

Figure — GDB debugging — breakpoints, watchpoints, step, next, backtrace

Step 7 — The degenerate cases (never leave a gap)

Every honest derivation must survive its extreme inputs. Here are the four corners.

PICTURE: four mini-panels, one per corner case, each showing what the red bar does.

Figure — GDB debugging — breakpoints, watchpoints, step, next, backtrace
Case What happens to Meaning
(hardware watchpoint, panel A) The debug register traps automatically on write — no per-line software check, so . Watchpoint is invisible.
(program does nothing, panel B) No lines run → no checks → no tax. Trivially, nothing is slower.
(long loop, panel C) The longer the run, the more traps pile up. Slowdown is unbounded.
variable out of scope (panel D) GDB deletes the watchpoint Once the watched local dies, there's nothing to watch — the tax stops, but so does your observation.

The one-picture summary

Everything above, compressed: a green baseline of lines, a red trap glued to each line, the ratio that turns "seconds" into "times slower," and the two regimes (software = tall red, hardware = no red).

Figure — GDB debugging — breakpoints, watchpoints, step, next, backtrace
Recall Feynman: the whole walkthrough in plain words

Imagine your program is a runner sprinting a track once — that sprint takes time , and the track has steps. A software watchpoint is a referee who forces the runner to fully stop, get inspected, and restart after every single step. Each stop-and-inspect costs a fixed chunk of time . Since there are steps, the referee adds of pure standing-around time. To feel how bad that is, compare the standing-around () to the actual running (): that ratio, plus for the run itself, is the slowdown . Because one inspection () takes way longer than one running step (), the standing-around dwarfs the run, and a 1-second sprint balloons to 101 seconds. The fix is the hardware watchpoint: instead of a referee stopping the runner every step, the track itself rings a bell only when the watched spot is stepped on — almost no stopping, so drops back to . That's why GDB picks hardware watchpoints whenever the chip's four debug registers are free.

Recall Quick self-test

Software watchpoint on a program with s, , s — what is ? ::: . Why does the leading in mean you can never beat normal speed? ::: Because , so always — the debugger only ever adds time, never removes it. A hardware watchpoint makes . Which symbol did it drive to (almost) zero, and how? ::: It drove (really, the number of traps) to near zero by using a debug register that traps only on an actual write instead of checking every line.