Debugging and problem solving
Debugging
B. W. Kernighan and P. J. Plauger. The Elements of Programming Style, 2nd edition, McGraw-Hill, 1982
Everyone knows that debugging is twice as hard as writing a program in the first place. So if you’re as clever as you can be when you write it, how will you ever debug it?
This is especially true for concurrent programs
Unpredictable interactions
Non-deterministic execution (reprodicibility problems)
Debugging concurrent programs
Most people, if you describe a train of events to them, will tell you what the result would be. They can put those events together in their minds, and argue from them that something will come to pass. There are few people, however, who, if you told them a result, would be able to evolve from their own inner consciousness what the steps were which led up to that result. This power is what I mean when I talk of reasoning backwards, or analytically.
-Sherlock Holmes in A Study in Scarlet by A. C. Doyle
Reasoning backwards
Start with a number of hypotheses H1, H2, etc.
For each sequence of observed events, check if there is a trace trace consistent with Hn that results in the observed sequence
If not, eliminate Hn
Race condition example
class Race1 { private int counter = 0; private synchronized int incr(int n) { counter++; return counter; } public void f () { int n = incr(); System.out.println("f() read " + n); } public void g () { int n = incr(); System.out.println("g() read " + n); } public static void main (String[] args) { try { final Race1 c = new Race1 (); // Create two threads that run our run () method. Thread t1 = new Thread () { public void run () {c.f();} }; Thread t2 = new Thread () { public void run () {c.g();} }; t1.start (); int n = c.incr(1); t2.start (); System.out.println("main() read " + n); // Wait for the threads to finish. t1.join (); t2.join (); } catch (InterruptedException e) { System.out.println ("Interrupted!"); } } }
When your colleague ran the program, three lines were printed. Unfortunately, he dropped the first two lines during copying from the terminal, so you only know the last line:
f() read 2
You would like to use your reasoning to deduce what the other lines were. The VM that ran the code was heavily loaded at that time, so you need to consider all possible orders of execution of code in different processes. Please state what was the first line printed, or list all possibilities if more than one is possible. Please include a short explanation of how you arrived at your answer.
Things to do while debugging
Try to reduce the program
Try to reduce the test case
Test your assumptions (hypotheses testing)
Use automatic techniques