HOWTO: Debugging for Newbies
This is the nth in a series of tutorials I don't have time to write, really. So it will be little more than a sketch. But I'm tired of telling this story in person, so I'd like to point people here first. Here's how to debug…
A) Prepare for debugging
- Make sure your code is ready to debug.
- Are you sure that there's a bug in it? Or is your specification and design just disorganized?
- Are you sure any part of it works at all? Can you even run the part that seems buggy properly?
- Have you formatted the code properly, commented it adequately, used reasonable names, etc? Have you passed all available static analysis tools, especially the warnings emitted by your compiler?
- Get in a reasonable debugging environment.
- Find a quiet place with adequate space. A clock should be prominently located. A soothing beverage should be available.
- You should have either a paper or electronic notebook open to take notes.
- You should have your target source code compiled and running on the proper platform.
- You should have all debugging and analysis tools you have access to within easy virtual reach. In particular, in the 21st century you need a debugger of some kind, if at all possible.
B) Characterize the failure.
- Can you set up the program to repeatedly fail? What is the minimum input needed to do this? Can you cut the program down to something simple that fails (without too much work)? Take notes.
- Stop the program in the debugger at (or if possible before) points of potential failure. Step through the program, noting the state and how it changes. Take notes.
C) Determine the root cause of the failure.
- Develop some hypotheses (note plural) as to the proximate causes of the observed failures (the defects or "bugs"). Take notes.
- For each hypothesis in turn, develop and apply experimental tests that will confirm or deny the hypothesis. This may involve modifying the program, using the debugger, running the program with different data, etc. Take notes.
- Once the bugs are adequately characterized, identify causes for the bug to get into the code (the root causes of the errors or "mistakes"). These may range from inadequate documentation of infrastructure to poor typing skills to sleepiness to whatever. Take notes.
- Put steps in place to remedy the root causes of the errors.
- For each error, identify other bugs introduced as a result of that error, and fix those also. Take notes.
D) Exercise the program carefully to make sure it has been debugged. Save all tests that failed before and pass now as "regression tests" to check that the bug doesn't return in the future.
When debugging:
- Don't get stuck. If you have pursued a given approach for 5 or 10 minutes without success, make a note and then abandon it temporarily. Banging harder typically won't budge it.
- Ask for help. Debugging is a good team activity.
- Take frequent breaks. Keep sessions short. Don't get sleepy; go to bed and try again in the morning. Remember that forcing it never works.
- Keep referring to your notebook. It tells the story of what you've tried, and what you still want to try.
- Use plenty of assertions. Don't remove them when debugging is complete (unless absolutely necessary for performance or correctness).
- Specific tools you should master in the Linux command line environment: gcc -Wall -g, gdb, valgrind.
- Don't get stuck. Take notes.
Hope this helps.