Debugging

    Put these two lines

    at the top of any program you're trying to debug, or may want to debug in the future. (If you think about it, that's every program ever, isn't it?)

    The strict pragma forces you to use a number of features that allow Perl to find errors during compile time. First and foremost, under strict, variables must be declared before they are used; in most cases, this means using my:

    1. use strict;
    2. my $foo = 7; # OK, normal variable
    3. print "foo is $fooo\n"; # Perl complains and aborts compilation

    Without strict, Perl would happily run the above programming, and you would be sad, wondering why $foo didn't have a value. Enabling strictures can save a lot of headache induced by typos.

    Additionally, strict disallows the use of most barewords:

    1. no strict;
    2. $foo = Lorem;
    3. print "$foo\n"; # Prints "Lorem"
    4.  
    5. use strict;
    6. my $foo = ipsum; # Complains about bareword
    7. $foo = (
    8. Lorem => 'ipsum' # OK, barewords allowed on left of =>
    9. );
    10.  
    11. $SIG{PIPE} = handler; # Complains
    12. $SIG{PIPE} = "handler"; # Also, OK, but above is preferred

    Finally, enabling strict throws a runtime error if you use http://perldoc.perl.org/perlref.html#Symbolic-references symbolic references:

    1. no strict;
    2. $name = "foo";
    3. $$name = "bar"; # Sets the variable $foo to 1
    4. print "$name $$name\n"; # Prints "foo bar"
    5.  
    6. use strict;
    7. my $name = "foo";
    8. $$name = "bar"; # Complains: can't use "foo" as ref

    The warnings pragma enables a whole host of useful complaints from Perl, letting you know about things in your program that you most likely didn't intend:

    1. use warnings;
    2. my $foo = ;
    3. $foo += 3;
    4. my $foo = 1; # Compains: redeclaration of variable
    5.  
    6. my $bar = '12fred34';
    7. my $baz = $bar + 1; # Complains: Argument "12fred34" isn't numeric
    8. # Complains: Name "main::baz" used only once

    It's amazing how often you'll see people complaining that a piece of code doesn't work:

    and then complain that the loop is broken. The problem here is often that the file $filename doesn't actually exist, and the open fails, but without a check, you'll never know. Replace it with:

    1. open( my $file, '<', $filename ) or die "Can't open $filename: $!";

    Sometimes the warning message doesn't explain as much as you'd like. For instance, why might you get this warning?

    1. Use of uninitialized value in string eq at /Library/Perl/5.8.6/WWW/Mechanize.pm line 695.

    Try running the code again with

    1. use diagnostics;

    at the top of the program. Now the warning looks like this:

    1. line 695 (#1)
    2. (W uninitialized) An undefined value was used as if it were already
    3. defined. It was interpreted as a "" or a 0, but maybe it was a mistake.
    4. To suppress this warning assign a defined value to your variables.
    5.  
    6. To help you figure out what was undefined, perl tells you what operation
    7. you used the undefined value in. Note, however, that perl optimizes your
    8. program and the operation displayed in the warning may not necessarily
    9. appear literally in your program. For example, "that $foo" is
    10. usually optimized into "that " . $foo, and the warning will refer to
    11. the concatenation (.) operator, even though there is no . in your
    12. program.

    That's a lot more information to help you on your way finding the program.

    Remember that you can specify modules and pragmata to be included on the command line, so you don't even have to edit your source code to use diagnostics. Run it again with the -M command line switch:

    1. Use of uninitialized value in string eq at /Library/Perl/5.8.6/WWW/Mechanize.pm line 695.

    So you can go see what the code at line 93 of that module is doing, but it doesn't tell you what your code was doing to get to that point. What you'd like to see is a trace of what subroutines were called.

    When Perl calls die or warn, it goes through the subroutines specified in $SIG{DIE} and $SIG{WARN}, respectively. If you modify those to be more useful functions than and CORE::warn, you've got a handy debugging tool. In this case, use the Carp module's confess function.

    At the top of your program, add these lines:

    1. use Carp qw( confess );
    2. $SIG{__DIE__} = \&confess;
    3. $SIG{__WARN__} = \&confess;

    Now, when the code calls warn or die, the Carp::confess function handles it. In this case, confess prints the original warning, followed by a stack trace, and then stops execution of the program.

    1. Use of uninitialized value in string eq at /Library/Perl/5.8.6/WWW/Mechanize.pm line 695.
    2. at /Library/Perl/5.8.6/WWW/Mechanize.pm line 695
    3. WWW::Mechanize::find_link('WWW::Mechanize=HASH(0x180e5bc)', 'n', 'undef') called at foo.pl line 17
    4. main::go_find_link('http://www.cnn.com') called at foo.pl line 8

    Now we have much more information to debug our code, including exactly what functions were called, and what parameters were passed. From here, we can easily see that the third argument to find_link is , which is a great place to start investigating.

    If you don't want to go through all the hoohah with overriding signal handlers, you can install the CPAN module Carp::Always.

    After installing Carp::Always, adding one line to your code


      Submit a PR to