Friday, February 02, 2007

Debugging by printing

There are two ways to debug a program. One is to study the source code and try to understand what the program is doing and try to figure out what could have gone wrong. This is a kind of static debugging. Doing a dry run of the program is at times overkill. The other is to let the program run and print its state information. We can reason out what might have gone wrong from the collected information.

Roughly speaking, state of a running program includes everything in the memory of the running program. But to make out what might have gone wrong, we only have to focus on what is really necessary.


When I say "let the program print its state information," it could be the modified program with a lot of print statements. Or it could be a debugger attached to the running process and printing the state information. It definitely helps to learn a few ways to print the state information. An incomplete list of useful information on how to print in various systems.

Language or Tool
Function/Command
Remarks
C
printf, fprintf
You could try fprintf(stderr, ...) and redirect the error output to a file.
C++
cout, cerr, clog
cerr << "Value of var is: " << var << endl;
Java
System.err.println, System.out.println,
java.util.logging.Logger
Logging API is very handy if you would like ship your code with logging facility.
make
$(info ...), $(warning ...), $(error ...)
Very handy when you want to know the value of a variable. Try $(info ${.VARIABLES}) to instantly figure out the list of variables set.
make
-d, --debug, --dry-run
-d and --debug print debugging information. --dry-run will tell you what all the actions to be taken without really taking them.
dbx
print, examine, dump
Examine is a very useful command if you would like to figure out any array boundary writes in a core dump. dump command prints all the local variables in the current stack frame.
Lisp
message, prin1

Perl
print
print STDERR ... will print in the standard error.
Python
print
Prints the given argument in the standard output. If you would like to print different types of items, you can give them in comma separated list.
Shell script
print, echo
The difference is print is an internal command in most of the shells, echo is an external command. This means that using echo will result in a new process being started for every echo statement.
Shell script
set -x
Cool command. This will print each command before it is executed. Be careful if you are giving passwords as arguments to any commands, as they will be printed in plain text on screen!


One of the most important things while logging any information is to print it along with some useful message, and possible workarounds if any. For e.g. the following is really really useless!
if(l == null) System.out.println("null value");

System.out.println("i is invalid");


Such messages are not only useless, but frustrating and misleading at times. Rather the following messages are very useful.

if(l == null)
System.out.println("Null value encountered while processing " +
"INI file lines.
Please check if all rows are formatted " +
"as \"name=value\"");


System.out.println("i is having illegal value [" + i + "]." +
" Expected i to be in the range 0 to 6 (inclusive)");

Keep in mind. We write once, but debug every time when there is an issue.


No comments: