Perl
  Home arrow Perl arrow Perl Debuggers in Detail
Dev Shed Forums  
Administration  
AJAX  
Apache  
BrainDump  
DHTML  
Flash  
Java  
JavaScript  
Multimedia  
MySQL  
Oracle  
Perl  
PHP  
Practices  
Python  
Reviews  
Security  
Smartphone Development  
Style-Sheets  
Web Services  
XML  
Zend  
Zope  
Mobile Linux  
App Generation ROI  
IBM® developerWorks  
Forums Sitemap  
E-Commerce Hosting  
Linux Web Hosting  
Managed Hosting  
Small Business Hosting  
VPS Hosting  
Weekly Newsletter

 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid  
Request Media Kit
Contact Us  
Site Map  
Privacy Policy  
Support  
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
Google.com  
PERL

Perl Debuggers in Detail
By: O'Reilly Media
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: starstarstarstarstar / 3
    2008-07-31


    Table of Contents:
  • Perl Debuggers in Detail
  • perl5db.pl
  • Alternative Debuggers
  • Devel::ebug
  • Other Debuggers
  • Summary

  • Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      error-file:tidyout.log Del.ici.ous error-file:tidyout.log Digg
      error-file:tidyout.log Blink error-file:tidyout.log Simpy
      error-file:tidyout.log Google error-file:tidyout.log Spurl
      error-file:tidyout.log Y! MyWeb error-file:tidyout.log Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article

     
     
    ADVERTISEMENT


    Perl Debuggers in Detail
    ( Page 1 of 6 )

    In this second part of a two-part series on debugging Perl, we will go beyond the author's favorite debugger and look at a number of alternative Perl debuggers. This article is excerpted from chapter four of the book Mastering Perl, written by Brian D Foy (O'Reilly; ISBN: 0596527241). Copyright © 2007 O'Reilly Media, Inc. All rights reserved. Used with permission from the publisher. Available from booksellers or direct from O'Reilly Media.

    Wrapping Subroutines

    I don’t have to copy a module file to change its behavior. I can override parts of it directly in my code. Damian Conway wrote a wonderful module called Hook::LexWrap to wrap a subroutine around another subroutine. That means that my wrapper subroutine can see the arguments coming in and the return values going out. I can inspect the values, or even change them if I like.

    I’ll start with my simple example program that adds a couple of numbers. As before, it has some problems because I’m passing it the wrong arguments since I can’t tell the difference between $n and $m, and have used $n twice in my call to add. Just running the program gives me the wrong answer, but I don’t know where the problem is:

      #!/usr/bin/perl
     
    # @ARGV = qw( 5 6 );

      my $n = shift @ARGV;
      my $m = $ARGV[0];

      print "The sum of $n and $m is " . add( $n, $n ) . "\n";

      sub add
             
    {
             
    my( $n, $m ) = @_;

              my $sum = $n + $m;

              return $sum;
              }

    I don’t want to change anything in the code, or, I should say, I want to look at what’s happening without affecting the statements that are already there. As before, I want everything back to normal when I’m finished debugging. Not editing the subroutine makes that easier.

    The Hook::LexWrap gives me a chance to do something right after I make a subroutine call and right before the subroutine returns. As the name suggests, it wraps the subroutine with another one to provide the magic. The Hook::LexWrap::wrap function takes the name of the subroutine it will wrap, add in this case, and then anonymous subroutines as pre- and posthandlers:

      #!/usr/bin/perl

      use Hook::LexWrap qw(wrap);

      my $n = shift @ARGV;
      my $m = $ARGV[0];

      wrap add,
             
    pre  => sub { print "I got the arguments: [@_]\n" },
             
    post => sub { print "The return value is going to be $_[-1]\n" }
              ;

      # this line has the error
      print "The sum of $n and $m is " . add( $n, $n ) . "\n";

      sub add
             
    {
             
    my( $n, $m ) = @_;

              my $sum = $n + $m;

              return $sum;
              }

    The prehandler sees the same argument list as my call to add. In this case I just output the list so I can see what it is. The posthandler gets the same arguments, but Hook::Lex Wrap adds another element, the return value, on the end of @_. In the posthandler,
    $_[-1] is always the return value. My program now outputs some useful debugging output, and I see that I’m passing the same argument twice:

      $ perl add_numbers.pl 5 6
      I got the arguments: [5 5 ]
      The return value is going to be 10
      The sum of 5 and 6 is 10

    In that output, notice the space after the last 5. Since wrap added an element to @_, even though it’s undef, I get a space between it and the preceding 5 when I interpolate the array in the double-quoted string.

    Hook::LexWrap has the magic to handle all the calling contexts too. It’s smart enough to handle scalar, list, and void contexts. In list context, that last element of @_ in the posthandler will be an array reference. In void context, it won’t be anything.

    It gets even better than that, though. Hook::LexWrap actually adds that extra element to @_ before it does anything. Look at the last output carefully. After the second argument, there’s a space between the second 5 and the closing square bracket. That’s the space between 5 and the undef value of the extra element in @_.

    In the prehandler, I can assign to that element, signaling to Hook::LexWrap that it should assume that it already has the return value, so it doesn’t need to actually run the original subroutine. If the subroutine isn’t doing what I need, I can force it to return the right value:

      #!/usr/bin/perl

      use Hook::LexWrap;

      my $n = shift @ARGV;
      my $m = $ARGV[0];

      {

      wrap add,
             
    pre  => sub {
                      print "I got the arguments: [@_]\n";
                      $_[-1] = "11";
                     
    },
             
    post => sub { print "The return value is going to be $_[-1]\n" }
             
    ;
      print "The sum of $n and $m is " . add( $n, $m ) . "\n";
      }

      sub add
             
    {
              my( $n, $m ) = @_;

              my $sum = $n + $m;

              return $sum;
              }

    Now that I’ve assigned to $_[-1] in my prehandler, the output is different. It doesn’t run the subroutine or the posthandler, and I get back 11:

      $ perl add_numbers.pl 5 6
      I got the arguments: [5 6 ]
      The sum of 5 and 6 is 11

    With my fake return value, I can give myself the right answer and get on with the right program, and do it without changing the subroutine I want to investigate. This can be especially handy if I’m working on a big problem where other things are broken, too. I know what I need to return from the subroutine so I make it do that until I fix the other parts, or at least investigate the rest of the program while the subroutine returns what it should. Sometimes eliminating a source of error, even temporarily, makes it easier to fix other things.



     
     
    >>> More Perl Articles          >>> More By O'Reilly Media
     

       

    PERL ARTICLES

    - More Perl Bits
    - Perl, Bit by Bit
    - Basic Charting with Perl
    - Using Getopt::Long: More Command Line Option...
    - Command Line Options in Perl: Using Getopt::...
    - Web Access with LWP
    - More Templating Tools for Perl
    - Site Layout with Perl Templating Tools
    - Build a Perl RSS Aggregator with Templating ...
    - Looping, Security, and Templating Tools
    - Perl: Bon Voyage Lists and Hashes
    - Templating Tools
    - Perl: Number Crunching
    - Perl Debuggers in Detail
    - Debugging Perl





    © 2003-2009 by Developer Shed. All rights reserved. DS Cluster 3 Hosted by Hostway
    For more Enterprise Application Development news, visit eWeek