Expert · Debugging and tools · topic 55 of 60 · 20 min
A method for debugging
Explanation
The steps
- Reproduce: find exact input and steps that make the bug appear every time. A bug you cannot reproduce cannot be confirmed fixed.
- Minimise: cut the input and the code down until removing anything more makes the bug disappear. Small cases make the cause obvious.
- Read: compiler warnings, sanitizer reports, the backtrace, the logs. The answer is often already printed.
- Hypothesise: state a specific guess ("count is negative because the loop runs one extra time").
- Test the hypothesis: a breakpoint, a watchpoint, a print, an assert. Confirm or reject it with evidence.
- Fix the cause, not the symptom: adding if (p == NULL) return; where it crashes may hide why p was NULL.
- Add a test that fails without the fix, and run the full test suite (with sanitizers).
The usual suspects for C crashes
| Symptom | Check first |
|---|---|
| Segmentation fault | NULL pointer, uninitialised pointer, out-of-bounds index, use after free, stack overflow from deep recursion |
| Garbage values | Uninitialised variables, missing return value, wrong printf format (%d for a long or double) |
| Works in debug, fails with -O2 | Undefined behaviour (signed overflow, strict aliasing, uninitialised reads) |
| Random crashes far from the bug | Earlier buffer overflow or double free corrupting memory |
| Strings print extra junk | Missing \0 terminator, buffer too small |
| Memory grows over time | Leaks on some code path (often an error path) |
| Infinite loop | Unsigned counter compared with >= 0, loop variable never changed, stray ; after while |
Printf debugging, done well
fprintf(stderr, "[%s:%d] i=%d len=%zu ptr=%p\n", __FILE__, __LINE__, i, len, (void *) ptr);Rubber-duck debugging
Explaining the code line by line to someone else, or even to a rubber duck on your desk, forces you to state what each line really does rather than what you meant it to do. Surprisingly often, the bug becomes obvious halfway through the explanation.
Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
A method for debugging · 1/6
In this lesson you will learn a reliable method for finding bugs.
Prefer a video by a teacher? Find free videos on “how to debug c programs systematically segmentation fault causes” on YouTube ↗
In real life: The crash that only happened on Tuesdays
A depot's bus-schedule program crashed only on some days. The developer reproduced it by setting the date, then minimised the input to one route with 31 stops. AddressSanitizer reported a stack-buffer-overflow: the stops array had 30 slots, and only Tuesday's timetable had a 31-stop route. The fix sized the array from the data (malloc) and added a test with 31 stops.
/* before */ char stop_names[30][40]; /* fixed at 30 */
/* after */ char (*stop_names)[40] = malloc((size_t) n_stops * sizeof *stop_names);Practice (0/3 done)
A program works with -O0 but prints wrong totals with -O2. What should you suspect first?
A string prints with extra strange characters at the end. Most likely cause?
Pick a real bug you hit during this course (or ask a friend for a buggy C program). Write a short report: the symptom, how you reproduced it, the minimised case, the tools you used and what they showed, your hypothesis, the fix, and the test you added.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Finding memory bugs with valgrindDebugging and tools · same module
- Hypothesis tests, p-values and A/B testingData Science, Machine Learning and AI · Probability and inference
- Debugging and performanceKotlin and Android App Development · Testing Android apps
- Building real projects: CMake, warnings, debuggers and sanitizersC++ Programming (modern C++ and DSA) · Exceptions, concurrency and building projects with CMake
- Troubleshooting tools and common faultsComputer Networking (CCNA level) · Troubleshooting and the CCNA exam
- Debugging like a pro: DevTools and VS CodeFrontend Web Development · Async JavaScript, modules and tools
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
What is the first step in debugging?
Answer: Reproduce the bug reliably
You cannot confirm a fix otherwise.
Why print debug output to stderr rather than stdout?
Answer: stderr is unbuffered, so lines appear even if the program crashes right after
Buffered stdout may be lost on a crash.
What does "fix the cause, not the symptom" mean?
Answer: Find why the bad value appeared instead of just guarding where it crashes
Guards can hide the real problem.
Which is a common cause of an infinite loop in C?
Answer: An unsigned counter compared with >= 0
An unsigned value is always >= 0.
What is the null hypothesis in an A/B test of two page designs?Related
Answer: There is no difference between the designs
H0 is the "nothing is happening" claim that we try to find evidence against.
Which flag adds debug information for gdb?Related
Which is a common cause of janky Compose screens?Related
Answer: Heavy work like sorting or formatting inside composable bodies
Move work to the ViewModel or remember it.
Which sanitizer finds use-after-free bugs?Related
Answer: AddressSanitizer
AddressSanitizer checks memory accesses.
From Building real projects: CMake, warnings, debuggers and sanitizers
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- This is the last topic of “Debugging and tools”. The module exam comes next.
- Module 11 exam: Debugging and tools · 12 questions · 25 min, without help. 5 topics of this module still to finish first.
- Then the next module, Embedded C, system calls and careers. 60 topics left in the course before the final exam.