Chapter 5. Tracing Code

“1545 Relay #70 Panel F (moth) in relay. First actual case of bug being found.”

Admiral Grace Hopper's Logbook September 9, 1945

In the phylogeny of debugging, the Protozoic approach consists of tossing

print "$variable = $variable
";

lines into the problem code at various places. Before we advance up the evolutionary ladder to interactive debuggers in Chapter 7, however, we have a lot of ground to cover.

We should not so readily disparage the humble print statement, because with a little tuning it can turn into a valuable tool. As we've already seen, the most basic kind of tracing statement prints out a variable name and its value. You can improve on it slightly by printing to STDERR instead of the currently selected filehandle.[1] It's also a good idea to make it stand out so that you remember to remove it when you're done debugging:

[1] Or even create a separate filehandle DEBUG for debugging output and redirect it wherever you want as development proceeds.

print STDERR "***DEBUG*** @names = @names
";

When you put an array in string context like that, it turns it into a string of all the array elements separated by spaces.[2] We find that trace statements like this are our major use of this feature.

[2] Actually, separated by the value of the $" variable, which you can change if you want.

If you want to economize on keystrokes, you can say warn instead:[3]

[3] The only way this would differ from printing to STDERR is if you happen to have installed a __WARN__ handler, in which case, presumably, you know what you're doing.

warn "***DEBUG*** Usernames: ", values %username, "
";

By sending your tracing output to STDERR, you have left undisturbed the normal output of your program to STDOUT, which means it can continue to run as a command in a pipeline sequence if you so desire. You can also output status information to STDERR in such a program (sometimes called a filter).

It's a good idea in this case to identify your program so that you can tell which command in the pipeline is talking to you:

% grep -li pseudo-hash /usr/local/perl/man/man1/*     
				| mytran | mail -s "Secrets you requested, tovarich" 
				[email protected]
mytran: Translating /usr/local/perl/man/man1/perldelta.1 into
Russian...
mytran: ***DEBUG*** $trans{perl} => 'zhemchuzhina'
mytran: Translating /usr/local/perl/man/man1/perldiag.1 into
Russian...
[...]

You do that by inserting $0 in your output string. $0 is the string with which your program was invoked. Note that this may include leading components of an absolute or relative path, so you may want to strip off everything before the filename component. The operating system-independent way to do this is:

use File::Basename;
my $prog = fileparse($0);
# $prog now contains the program name along with any suffix

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset