Home > Articles

This chapter is from the book

Item 19: Automate Debugging Tasks

You may find yourself with many possible discrete causes for a failure and no easy way to deduce which of them is the culprit. To identify it, you can write a small routine or a script that will perform an exhaustive search through all cases that might cause the problem. This works well when the number of cases would make it difficult to test them by hand, but possible to go through them in a loop. Iterating through 500 characters is a case that can be automated; doing an exhaustive search of all strings of user input is not.

Here is an example. After an upgrade, a computer began to delay the execution of the which command. Changing the long command search path (the Windows and Unix PATH environment variable) to /usr/bin removed the delay but left the question: Which of the path’s 26 elements was causing it? The following Unix shell script (run on the Windows machine through Cygwin) displayed the elapsed time for each path’s component.

# Obtain path
echo $PATH |
# Split the :-separated path into separate lines
sed 's/:/\n/g' |
# For each line (path element)
while read path ; do
  # Display elapsed time for searching through it
  PATH=$path:/usr/bin time -f "%e $path" which ls >/dev/null
done

Here is (part of) the script’s output:

0.01 /usr/local/bin
0.01 /cygdrive/c/ProgramData/Oracle/Java/javapath
0.01 /cygdrive/c/Python33
4.55 /
0.02 /cygdrive/c/usr/local/bin
0.01 /usr/bin
0.01 /cygdrive/c/usr/bin
0.01 /cygdrive/c/Windows/system32
0.01 /cygdrive/c/Windows
0.01 .

As you can clearly see, the problem is caused by an element consisting of a single slash, which had inadvertently crept into the path. Tracing the execution of the which command (see Item 58: “Trace the Code’s Execution”), revealed the problem’s root cause: The which command appended a slash to each path element, and on Windows a path starting with a double slash triggered a discovery process for network drives.

If it’s difficult to perform the exhaustive search by scripting the software you’re investigating, you can embed in the program a small routine for the same purpose. The routine can generate all the cases algorithmically (e.g., by iterating through some values). Alternately, it can read them from an external file, where you can generate them via a more sophisticated script or by scrapping data from existing execution logs.

Finally, there are also tools that can instrument your code to detect API violations, memory buffer overflows, and race conditions (see Item 59: “Use Dynamic Program Analysis Tools” and Item 62: “Uncover Deadlocks and Race Conditions with Specialized Tools”). For some of these tools, the analysis of a test run that used to take a few seconds can take tens of minutes. Nevertheless, the debugging time they can save you is well worth the wait.

Things to Remember

  • Automate the exhaustive searching for failures; computer time is cheap, yours is expensive.

  • + Share This
  • 🔖 Save To Your Account