O'Reilly News
Proboscis Monkey    Perl Debugging for Beginners

by John Callender, author of Perl for Web Site Management


17 October 2001

In a previous oreilly.com article, (Confessions of an Accidental Programmer), I wrote about the phenomenon of accidental programmers: people who come to programming from some other field, without the benefit of formal instruction. Perl's popularity for Web-content creation has led to an explosion in the number of accidental programmers. As someone who followed that path, I'm sympathetic to the difficulties beginners face in their efforts to become proficient with Perl. For someone just starting out, even a simple "Hello, world" script can represent a real challenge.

  Perl for Web Site Management
Sample Chapter
Full Description

In my book, Perl for Web Site Management, which I wrote specifically for accidental programmers, I write tongue-in-cheek of "The Joy of Debugging," and I warn novice programmers that they're going to experience a lot of this particular joy. Whether you are a beginning programmer or an expert, you're going to spend a great deal of time in the debugging phase: tracking down and squashing the silly mistakes that keep your programs from running as you intended.

Sometimes the mistake will be obvious: you left off a semicolon or the closing quotation mark in a quoted string. Other times the mistake will be maddeningly obscure (at least until you identify it, at which point it, too, will become obvious): you gave the wrong arguments to a function, or you were confused about some aspect of Perl behavior.

Debugging is a specialized skill and it takes practice to become adept at it. Debugging is somewhat like car repair; an experienced mechanic can ask a few questions, listen to the engine for a second, and immediately tell you what's wrong with your car and what it will take to fix it. Meanwhile, a novice mechanic will pull apart the transmission when the real problem is a broken light on the dashboard.

As you learn about programming you will frequently feel like that novice mechanic, banging your head against the keyboard for what seems like hours, only to discover the problem was actually in a completely different part of your script than where you were looking. This is OK. It's a good thing. It's how you learn.

With that said, I'd like to offer ten debugging tips gleaned from my own experience that will help you learn more quickly.

  1. Pay close attention to error messages.

    Perl does its best to give you useful error messages. Read the message carefully. It will usually report the line number in your script where the problem occurred, so go to that line number and see if you can figure out what's going on. (Be aware that the problem might be on an earlier line. This is because you can make a mistake that looks like valid Perl code but which doesn't trigger an error until later on in the script. Forgetting to properly terminate quoted strings is a good example of this.)

    Similarly, some mistakes will produce multiple error messages. In that case, pay most attention to the first error message since the subsequent ones may go away once the first problem is fixed.

  2. Use the -w switch to turn on Perl's warnings feature.

    By putting a space and -w at the end of the shebang line that starts off your Perl script, you tell Perl to warn you about things it thinks might be problems in your script. (With recent versions of Perl, 5.6.0 and later, you can achieve the same thing by putting the line use warnings near the top of the script.)

  3. Use perl -c scriptname, or perl -wc scriptname, (with scriptname replaced by the actual name of your script) to do a compile check before running your script for real.

    By entering the command perl -c scriptname or perl -wc scriptname, you cause Perl to try to compile your script without actually running it. The -c version compiles the script without invoking the warnings feature; the -wc version compiles it with warnings turned on. In either case, you can get feedback on any problems your script might have, without having to actually run it.

  4. Take a step back.

    Vary your mental perspective. Try to consider the problem in a larger context. Perhaps the problem is not in the chunk of code you think it is, but in some untested assumption elsewhere in your script.

  5. Try to isolate the problem.

    By commenting out chunks of code, then rerunning the script, you can often narrow down where the problem is occurring. Even better is to avoid the need for this by building and debugging the script in small increments. Create a simple framework first, get it working, then add increasingly complex features on, testing each component before moving to the next. In this way you will uncover bugs as you go, and it will usually be obvious where the bug resides; it is in the small section of code you just added. While it may seem faster to code up the whole thing first, then do all the debugging at the end, it rarely works out that way.

  6. Use print statements to test your assumptions.

    By sprinkling temporary print statements in your script, you can often track down where a problem is occurring. For example, if you think that at a certain point a variable should contain one value, but the script is acting as if it contains something else, add a statement to print out the contents of the variable at that point and rerun the script. Similarly, you can use print statements to indicate the flow of execution through the script: "I'm in the if block now," "I'm looping through the foreach loop with a value of $foo in my index variable," and so on.

  7. Use the Data::Dumper module to get a snapshot of complex data structures.

    This is a slightly fancier version of the print-your-variable's-contents suggestion from the previous tip. If your Perl programming has progressed to the point where you are using multilevel data structures (like hashes of hashes), you can use the standard Data::Dumper module's Dumper function to print them out for debugging purposes. For example, if you have a hash of hashes named %HoH in your script, you can print it out with the following two lines:

    use Data::Dumper;
    print Dumper(\%HoH);

  8. Use a test script to clarify confusing aspects of Perl behavior.

    As an alternative to the last several tips, which deal with altering your main script to get a better picture of what's going on, you can often cut to the heart of a debugging problem by writing a separate, stand-alone test script. With a simplified test case, you can focus on one issue at a time. This sort of divide-and-conquer approach is one of the keys to effective debugging.

  9. Use the strict pragma.

    Perl is a great language for writing quick, one-off scripts, in part because of its default behavior of having new variables simply spring into existence on first mention. This can lead to problems as your script grows, however. A typo in the name of a variable will mean that your script is suddenly using a new, different variable from the one you intended, which can be a real head-scratcher to debug. By putting the following line near the top of the script

    use strict;
    

    you are telling Perl that you are willing to be held to a higher standard. In particular, you're saying you are willing to declare all your variables (typically, with a my declaration) before using them. Besides protecting you from typos in your variable names (because the script will abort with an error message during the initial compilation phase if it encounters an undeclared variable), this also lets you properly "scope" your variables, thereby limiting their visibility, rather than letting them be "global" variables that could conceivably interact with other variables of the same name elsewhere in the script. All of this translates into big savings in debugging time.

  10. Resist the temptation to attribute the problem to some previously undiscovered bug in Perl.

    Every novice Perl programmer eventually comes up against a bug that defies all efforts to identify and eradicate it. As the programmer's frustration level mounts, an idea begins to creep into his or her head: it must not be a problem in the script, but is something broken in Perl itself. I've thought this at least a dozen times, and I was always wrong. Take my word on this one: it's almost certainly a bug in your script, not in Perl.

One thing I haven't written about in this article is the Perl debugger and I've done it for a reason: while useful, the debugger can be overwhelming for a beginner. That's why I suggest you stick with things like embedded print statements for the time being. Still, if you're curious, or if you have a really thorny debugging problem and you think the debugger might help, see the perldebug man page for more information. If your version of Perl is recent enough (5.6.1 or later), the perldebtut man page, which gives a beginner-friendly introduction, will also be available. You invoke the debugger by running Perl with the -d command-line switch by entering the following at the shell prompt:

[jbc@andros jbc] perl -d scriptname.plx 

What this will do is put you in a special debugging mode, where you can step through your program one statement at a time and do interesting things like examine the current contents of variables.

That's it. Happy debugging!


John Callender is an independent consultant specializing in Web development. He has been a teacher, a writer, an editor, and a network administrator. In his spare time, he enjoys sailing, bird watching, and learning more about computers.


O'Reilly & Associates will soon release (October 2001) Perl for Web Site Management.


O'Reilly Home | O'Reilly Bookstores | How to Order | O'Reilly Contacts
International | About O'Reilly | Affiliated Companies


© 2001, O'Reilly & Associates, Inc.
webmaster@oreilly.com