A Debugging Method That Always Works
beginner10 min readLesson 50 of 204
Reproduce, read the evidence, bisect, form one hypothesis at a time — the loop professionals run, plus the warning-fueled workflow.
The loop
- Reproduce deterministically. A bug you can trigger on demand is half-dead. Find the smallest input that still fails.
- Read the evidence. The crash message, the assert text, the wrong value — each names a neighborhood. Compiler warnings are free bug reports; this course compiles with
-Wall -Wextra -Wpedanticand so should you. - Form ONE hypothesis. "The index is off by one at the last element" — not "something is wrong with loops".
- Test it cheaply. Print the suspect values, or run under a debugger (breakpoints, step, inspect — learn your IDE's debugger; it beats print for anything nontrivial).
- Fix, then re-run the WHOLE suite — not just the failing case, or you just traded one bug for another.
- Add the regression test. The bug you just killed must never resurrect silently.
Bisecting: when you have no idea
Comment out / skip half the pipeline; does it still fail? The bug lives in the failing half. Repeat. Log₂ of a thousand-line program is about ten experiments — bisection turns "impossible" into "twenty minutes".
The classic beginner traps, one last time
- Uninitialized variable (garbage that "works sometimes").
- Off-by-one at boundaries (test the empty and single cases explicitly).
=in a condition.- Integer division where a double was meant.
- Modifying a container while range-for iterates it (invalidated iterators — push_back during a range-for over the same vector is UB; collect changes, apply after).
Debugging is the skill
Interviewers know it, senior engineers know it: the scarce skill is not writing code, it is finding out why the code lies. Every module's debugging exercises trained this loop; module 18 will lean on it under time pressure.