Debugging P.J. Drongowski 26 August 2004 * "Debugging" is the process of finding and removing logic errors * Debugging is brain work + It involves logic and inference + It involves cause and effect + It requires an understanding of the program structure, its intended behavior and its actual behavior + Trial and error is ineffective -- production software systems are too big and complicated * Debugging is detective work + A good detective collects evidence + The detective evaluates the evidence and develops a hypothesis + The detective tests the hypothesis + Depending upon the outcome, the detective adjusts the hypothesis and retests, or makes an arrest. * We need to be detectives * Collect evidence + Design a comprehensive set of test cases to reveal the presence of errors; Run the test cases and gather actual results + The program can be instrumented to observe values of variables, conditions, etc. at specific execution points - The term "instrument" comes from real :-) science and engineering where an instrument is used to measure and observe physical phenomena, e.g., a volt meter - Insert output statements ("<<", printf) at key locations to display values of variables - Insert assert macros at key locations to test conditions - Use a debugger (gdb) to stop execution at specific points during execution and display the value of variables, etc. * Evaluate evidence and develop a hypothesis + Separately obtain or compute "known good" results and carefully compare actual results with known good results + Determine how observed values differ from your expectations or the desired outcome + Look for patterns of behavior, patterns in the output + Successively isolate the problem to a particular class, method and program statement * Test the hypothesis + Add new test cases to more thoroughly exercise the part of the program that is the suspected culprit; professional programmers rejoice when they find a "reproducer" (What is a "reproducer?") + Add instrumentation to the program to collect more evidence to either validate or refute the hypothesis + "Desk check" your program -- manually execute the program with actual values (Desk checking was SOP when turnaround times were long) + Add a carefully considered change to the program to repair the bug * Run the program and evaluate the outcome + Does the program work correctly with respect to the known good results or expected output? + If not, collect more evidence and reformulate the hypothesis or even abandon the hypothesis; Don't box yourself in! * Some bugs are just darned hard to find + Use of assignment (=) in a conditional expression instead of equals (==) + Clause is properly indented, but the enclosing braces are missing (A clause is the "then" part of an "if," the "else" part of an "if," the body of loop, etc.) + Transient errors (e.g., synchronization failure) of a type usually found in real-time systems or operating systems * What are assert macros and how do I use them? * How do I write my own debugging macros or utilities? * What is the GNU debugger gdb and how I get started with it? * Other debugging techniques + Writing intermediate results to a log file + Performing a "binary search" to isolate error to a single module