Debugging
What is debugging?
During/after coding, before/during/after testing
Bring the program to a state where it appears to be bug-free (but this is a lie)
Estimate 20-40% of programming effort
"Secret": No good books (AFAIK), no chapter in normal programming books, nothin'
How to debug
Given a failure of the software:
Find the causes ("faults") leading to that failure
Find the root causes of those faults
Figure out and apply a repair
Check the repair
Does it fix the failures?
Does it cause new failures?
Key activity: diagnosis
Like in medicine or car repair: "It doesn't work; what's happening and what can be done?"
Diagnosis is hypothesis formation and testing
- What possible reasons might there be for observed symptoms?
- Can those reasons be ruled out by what is known so far?
- If not, can we do tests to rule each reason out or increase our belief that it is the correct one?
- Repeat until exactly one possible reason remains, and it looks really likely to be true.
Diagnosis: gathering evidence
Observation: what do you see?
- What is being printed at compile time? At runtime?
- What is timing like? Unexpected pauses? Unexpectedly fast?
- What side effects on the system do you observe?
Analysis: what do you know?
- How should the system work?
- What kinds of bugs should be expected?
Most bugs can be diagnosed without "extra" experiments: "psychic debugging"
Preparing code for debugging
"Real programmers don't comment. It was hard to write--it should be hard to read and harder to understand."
Code should have a spec, simple tests, and pseudocode
Formatting should be as clean as possible
- Consistent indentation
- Consistent liberal use of whitespace
- Good names
- Idiomatic
Code should be instrumented appropriately
Debugging pre-inspection
Read the code in question carefully. Look for things that are wrong or unclear
Explain the code to someone. Have them look at it too
Most bugs are easily found and fixed by inspection alone
Debugging tools: your brain
Are you sure the spec and tests are correct?
White-box: what kinds of similar inputs might produce the same program misbehavior?
Black-box: what properties distinguish misbehaving inputs?
Is the timing as expected?
Are your current hypotheses consistent with everything you have observed or can observe?
Debugging tools: print() function
For a specific hypothesis, stick a print() in that will either disconfirm or confirm the hypothesis
Works in a huge variety of situations
But don't spam instrumentation everywhere, or you will get confused by it
Can use print() for exploring program behavior ("tracing"), but beware: one can waste a lot of time doing this without learning anything.
Always best to know what the question is before you start looking for the answer
Debugging tools: "debugger"
A modern debugger will happily provide you the ability to
- Step through your program one statement at a time
- Run until a given program line is reached
- Examine/change variable values anytime stopped
Except the debugger is really fragile and hard to use
In particular, doesn't interact well with I/O and the like
In general, debugger is tool of last resort
Common bugs
Two basic kinds:
- Bad control flow
- Just plain calculating the wrong thing
Examples
- Off-by-one "fencepost" errors
- Copy-and-paste calculation errors
- Typos/"Thinkos"
- Failure to design to the spec
- Failure to understand/implement the design
Root Cause Analysis
It's not enough to find the line of code that "causes the bug"
You want to find out how that line got there
In software, faults are caused by mistakes ("errors") that were made by a human (usually you)
With the "root causes" found, you can:
Correct all the faults caused by that error
Take steps to make that error less likely in the future
Repair
Craft fixes that fix the faults properly
- This may involve changing the design or revising the specification
Apply the fixes, then test everything carefully
- Did the problem get fixed?
- Are there new problems?
Post-repair
Propagate: Look for other places where faults may have been inserted due to the same root causes
Think hard about how those faults got there. What are you going to do to avoid this in the future?
Backups, versions and source code management
It is really easy to get the buggy version and the fixed version and the version you are working on right now mixed up
Source code management system is mandatory; avoid "backup files"
Parting thoughts
Don't get stuck!
Interrupt yourself every few minutes and see if you're making real progress
If you are stuck, many strategies are available:
- Try a different approach
- Take a break
- Ask for help
Don't get discouraged
The most experience programmers still make a lot of bugs and have a hard time fixing them
The bugs you will make are all fixable