Debugging
Systematic debugging approach, hardware and software breakpoints, debuggers (gdb, lldb, Visual Studio), sanitizers, and logging strategy.
4 questions
JuniorDebuggingVery commonWhy does if (x = 0) take the wrong branch?
Why does if (x = 0) take the wrong branch?
x = 0 is assignment, not comparison: it stores 0 into x and the expression evaluates to 0 (false), so the else runs and x is now 0. The author meant ==. Compilers warn with -Wparentheses; some style guides write if (0 == x).
Common mistakes
- ✗Reading
=as==inside a condition - ✗Expecting a compile error rather than a silent wrong branch
- ✗Not enabling -Wparentheses to catch the typo
Follow-up questions
- →Why does writing
if (0 == x)turn this typo into a compile error? - →What does the value of an assignment expression equal in C++?
JuniorTheoryCommonWhat is debugging and what are the basic techniques?
What is debugging and what are the basic techniques?
Debugging is locating and removing defects. Basic techniques: reading the stack trace, setting breakpoints in gdb/lldb, single-stepping, printf-debug for quick checks, binary-search bisection of suspect commits, sanitizers (-fsanitize=address), and structured logging.
Common mistakes
- ✗Debugging on the optimized build without realising the compiler reordered or elided variables — use
-Ogfor a debugger-friendly optimized build - ✗Chasing the symptom (the crash line) instead of the cause — the actual defect is often N steps earlier in the call stack
- ✗Forgetting to reproduce the bug deterministically before attempting a fix — non-reproducible fixes are guesses
Follow-up questions
- →What is the difference between
-O0,-Og, and-O2for debug experience? - →How does
rr(record-replay) change how you debug intermittent bugs?
MiddleTheoryCommonHow do you systematically debug C++ code, and which tools support it?
How do you systematically debug C++ code, and which tools support it?
Reproduce reliably, isolate by binary search, form a hypothesis and test it. Use gdb/lldb for stepping, sanitizers (ASan/UBSan/TSan) for memory and race bugs, Valgrind for leaks, perf for profiling, structured logs in production.
Common mistakes
- ✗Changing several things at once — you won't know which change fixed it; change one variable at a time
- ✗Stepping through a release build — inlining and reordering make the debugger jump around; use a debug build or
RelWithDebInfo - ✗Running ASan/TSan in production — sanitizers add 2-10× overhead; reserve them for CI and local reproductions
Follow-up questions
- →How do you debug a crash that only happens in production but not in dev builds?
- →What is
rr(Mozilla Record and Replay) and when does it beatgdb?
SeniorTheoryOccasionalHow do hardware and software breakpoints work?
How do hardware and software breakpoints work?
Software breakpoints replace a byte with INT 3 and trap SIGTRAP; unlimited but need writable memory. Hardware breakpoints use CPU debug registers and enable watchpoints, limited to 4 on x86.
Common mistakes
- ✗Setting a watchpoint on a local variable after the function returns — the stack frame is gone; the watched address now belongs to another variable
- ✗Thinking software breakpoints work in ROM or execute-only memory — the debugger can't write to ROM; hardware breakpoints are the only option
- ✗Forgetting that
INT 3changes timing — in race conditions, inserting a software breakpoint changes the interleaving; use logging or hardware watchpoints which have less impact
Follow-up questions
- →How does gdb implement a conditional breakpoint without stopping at every hit?
- →What is the difference between step-into, step-over, and step-out in a debugger?