Question

Are there any other ways for debugging Perl apart from Data::Dumper and perl -d?

Was it helpful?

Solution

Available tools for debugging

There are several tools available in Perl for debugging and similar tasks.


Built-in command line debugger.

perl -d yourcode.pl

Devel::ptkdb

Perl/Tk based graphical debugger by Andrew E. Page.


Regex Coach

This a free tool running both on Linux and Windows written in Lisp. Source code is not available.


Rx: A Regex Debugger for Perl

The Perl Regex debugger and an article about it written by Mark Jason Dominus.


A GUI for the Perl Debugger

OTHER TIPS

There are lots of things out there to help you:

  • Devel::Trace - print every line that executes
  • Carp::REPL - drop into a REPL* when the code throws a warning
  • Devel::ebug - a debugger you can control from Perl code
  • Enbugger - use debugger at runtime regardless of whether your process was started with debugging

I like Devel::Trace. Basically it gives you an execution dump, showing you the code paths.

On another side, Test Driven Development is all the rage now, so you could also be interested in profiling tools like Devel::NYTProf for highly advanced testing. See this Tim bunce's blog post for an interesting overview.

I use ActiveState Komodo for step-by-step debugging.

Eclipse has a step by step debugger for its EPIC plugin.

Personally I prefer the ActiveState version. It just seems more solid and stable, but it does cost (and work is paying for me). If it was my money then I would use Eclipse and EPIC as these are free.

The best debugging aids are small routines, short scopes, limited side effects, and lots of tests. Stop bugs before they hatch.

My usual range of tools is:

  • print statements and Data::Dumper for simple cases
  • perl -d

That's usually enough. There is ddd; I heard it's quite nice, but never played with it.

For some tasks (which are not really debugging, but close to it) I use Devel::NYTProf.

Some people use print statements in order to see what's going on in sections of a program that aren't doing what they thought the code would do. (I.e., as a way of checking what is actually contained in a variable at a given point of execution.)

That said, the question is pretty vague. Is there something you are trying to do that Data::Dumper and perl -d aren't helping with?

Depending on what you're doing, Log::Log4perl provides an easy way to manage the 'print' style of debugging particularly in bigger applications:

  • provides various logging levels (Debug, Info, Error, Warning, Fatal)
  • controlled from config files (easy to have debugging on development box, only errors on production box, for example)
  • configurable by sections of your application (e.g. web app in one log file at one level, cron scripts in another at a different log level)
  • configurable by Class - easy to quieten noisy modules, or add detailed debugging to somewhere deep within an app

Test::More for writing basic tests, Hook::LexWrap, Test::MockObject, Test::Deep, Test::MockTime, Test::WWW::Mechanize and many others for advanced tests. Attribute::Signature for checking sub params. Carp::Assert for contract-based programming.

Devel::Ebug::Wx or Devel::ptkdb (and soon better support in Padre) can be used for easier debugging.

Emacs, hands down.

   emacs my_script.pl
   M-x perldb
   Emacs will prompt you :
   Run perldb (like this): perl my_script.pl
   Hit enter (or add command line switches)

   Now use the debugger as usual.
   Type 'c' to continue executing the code, which will now follow
   your code as you execute through it.

   Emacs is fully integrated with its debuggers and will make debugging perl code nearly trivial.

Use, Devel::SimpleTrace, for the most elegant seemless stateless-debugging.

perl -MDevel::SimpleTrace -we'warn "main"; sub foo{ warn "outer"; sub { warn "inner" } }; foo()->()'

If you don't like perl -d then Devel::REPL and Carp::REPL are both nice alternatives.

Personally, I'm a big fan of Smart::Comments. Makes tracing dead simple, no need to strip it out again, either.

use Smart::Comments -ENV;
...
sub myroutine {
    my ($self, @args) = @_ ;
    ### args: @args
    ...
}

If Smart_Comments has been set in the environment, the lines commencing with ### are converted to debug output, with Dumper() used automagically. If the environment variable isn't set, the debug stuff is completely inert.

It has heaps of features, and will produce progress bars, warnings, abort conditions as well as plain old debug output.

Appropriate tests are all good, and I'm not dismissing a good TDD development methodology, but when trying to get to the bottom of an existing bug, Smart::Comments is the go.

Generally I use

perl -d

for debugging.

YOu can also use Eclipse Perl Integration (EPIC) plug-in for Eclipse It offers a rich debugging environment available and integrated with the EPIC Perl development environment. You can use it and is generally helpful.

During development, I like to embed printf statements in strategic places (not too many) which are enabled with a debug flag like this:

printf("h='$h', j='$j', ... (%d)\n", __LINE__) if $debug;

where the debug flag is defined at the top of the script:

my $debug = $ENV{DEBUG} || 0;

Now instead of having to remember to comment out all of the printf lines, I just run the script as follows:

DEBUG=1 ./script.pl

After testing when everything is ready for production, the debug lines can be removed:

cat script.pl | grep -v 'if $debug;'

Writing tests can mostly decrease debugging time, I think.

Some Other methods

CGI::Dump

Benchmark

Command-line options 

__DATA__ & <DATA> 

$.

__FILE__ & __LINE__ 

warn() & die() 

Debug::Statements provides an easy way to insert and enable/disable print statements for debugging.

The d() function prints the name of your variable, its value, and your subroutine name. The implementation been optimized to minimize programmer keystrokes.

Here is sample code to get you started:

my $myvar = 'some value';
my @list = ('zero', 1, 'two', "3");
my %hash = ('one' => 2, 'three' => 4);

use Debug::Statements;
my $d = 1;
d "Hello world";
d '$myvar';
d '@list %hash';

Output:

DEBUG sub mysub:  Hello world
DEBUG sub mysub:  $myvar = 'some value'
DEBUG sub mysub:  @list = [
  'zero',
  1,
  'two',
  '3'
]
DEBUG sub mysub:  %hash = {
  'one' => 2,
  'three' => 4
}

Many options are available to customize the output. Full documentation can be found on CPAN.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top