Softpanorama
(slightly skeptical) Open Source Software Educational Society

May the source be with you, but remember the KISS principle ;-)

Softpanorama Search

Perl Debugging

Old News
;-)

See also

Recommended Books Recommended Links

Perl for Unix System Administrators

Reference

Perl Language

Perl Xref Debugging regular expressions Perlrun man page Perl Style Regular expressions Perl Programming Environment Pipes
Debugging Software Testing Program understanding Pretty Printing Perl Tips Humor Etc

Debugging of Perl scripts is a challenging problem due to the complexity and power of the language. The quality of the debugger is good, but still it is a free open source implementation and as such it is limited to command line. The debugger's command-line history mechanism provides command-line editing like many shells but you need correct build of Perl interpreter to enjoy this (you can also execute previous lines with using exclamation point syntax).

Also Perl is very high level language and to understand to what part of the program you should attribute a particular error message is rather hard in the current Perl implementation. Here recommendations of the famous book How to Solve It are directly applicable and I highly recommend it for any Perl student.

Minimal set of commands that you probably need to know in order to be able to use Perl debugger includes the following 12 commands:
  1. s - single step including stepping into subs
  2. n - steps without stepping into subroutines. 
  3. c - continue processing until a break of some sort
  4. r - continue running until you do a return from the current sub. Essentially you  tell the Perl debugger to finish executing the subroutine and return to the statement after the subroutine call.
  5. v - shows a "window" of code around the current line. More convenient then l in many cases.
  6. b - sets a break point (uses line number *or* sub name)
  7. X - displays value of variables (*including* arrays & hashes), for example:
      DB<6> X regarray
  8. w - Add a global watch-expression. We hope you know what one of these is, because they're supposed to be obvious.
  9. T - displays a stack back trace
  10. L - list all the breaks
  11. D - delete all the breaks
  12. R - restart

csh-like history mechanism

The debugger prompt is something like:

DB<8>

where the number shows how many commands you've executed. A csh-like history mechanism allows you to access previous commands by number. For example, !17 would repeat command number 17. The number of angle brackets indicates the depth of the debugger. For example, you get more than one set of brackets if you're already at a breakpoint and then print out the result of a function call that itself also has a breakpoint.

Some additional tips

- You can display the lines immediately preceding the last displayed line by entering the - command.

V [pkg [vars]]
Display all (or some) variables in package (defaulting to main) using a data pretty-printer
! number
Redo a previous command (defaults to the previous command).
l min+incr
List incr+1 lines starting at min.

Switching to step-by-step execution from within the program

You can switch to step-by-step execution using Perl debugger from within your Perl program itself. to transfer control back to the debugger use the following statement, which is harmless if the debugger is not running:

$DB::single = 1;
If you set $DB::single to 2, it's equivalent to the n command, whereas a value of 1 emulates the s command. The $DB::trace variable should be set to 1 to simulate the t command.

A Watchful Eye

You can set a watch-expression (an expression which triggers a halt if its value changes) with the "w" command, as in the following example:


DB<1> w $count
DB<<3>> L
Watch-expressions:
$count

Now that the watch-expression has been set, you can see how it works by writing some code to alter the value of the $count variable. The debugger will display a message every time the variable's value changes.


Notes:
  • This is a Spartan WHYFF (We Help You For Free) site written by people for whom English is not a native language. Some amount of grammar and spelling errors should be expected.
  • The site contain some broken links as it develops like a living tree... Please try to use Google, Open directory, etc. to find a replacement link (see HOWTO search the WEB for details). We would appreciate if you can mail us a correct link.
Google Search
Open directory

Research Index


Old News ;-)

[Jan 22, 2009] DB - programmatic interface to the Perl debugging API (draft ...

DB - programmatic interface to the Perl debugging API (draft, subject to change) ... like debugging with a command line and GUI at the same time, debugging debuggers etc. ... This module attempts to be squeaky clean w.r.t use strict; ...
sunsite.ualberta.ca/Documentation/Misc/perl-5.6.1/lib/DB.html - 12k - Cached - Similar pages

[Mar 13, 2007] Programming in Perl - Debugging

On this page, I will post aides and tools that Perl provides which allow you to more efficently debug your Perl code. I will post updates as we cover material necessary for understanding the tools mentioned.
CGI::Dump
Dump is one of the functions exported in CGI.pm's :standard set. It's functionality is similar to that of Data::Dumper. Rather than pretty-printing a complex data structure, however, this module pretty-prints all of the parameters passed to your CGI script. That is to say that when called, it generates an HTML list of each parameter's name and value, so that you can see exactly what parameters were passed to your script. Don't forget that you must print the return value of this function - it doesn't do any printing on its own.
use CGI qw/:standard/;
print Dump;
Benchmark
As you know by now, one of Perl's mottos is "There's More Than One Way To Do It" (TMTOWTDI ©). This is usually a Good Thing, but can occasionally lead to confusion. One of the most common forms of confusion that Perl's verstaility causes is wondering which of multiple ways one should use to get the job done most quickly.

Analyzing two or more chunks of code to see how they compare time-wise is known as "Benchmarking". Perl provides a standard module that will Benchmark your code for you. It is named, unsurprisingly, Benchmark. Benchmark provides several helpful subroutines, but the most common is called cmpthese(). This subroutine takes two arguments: The number of iterations to run each method, and a hashref containing the code blocks (subroutines) you want to compare, keyed by a label for each block. It will run each subroutine the number of times specified, and then print out statistics telling you how they compare.

For example, my solution to ICA5 contained three different ways of creating a two dimensional array. Which one of these ways is "best"? Let's have Benchmark tell us:

#!/usr/bin/perl
use strict;
use warnings;
use Benchmark 'cmpthese';

sub explicit {
    my @two_d = ([ ('x') x 10 ],
                 [ ('x') x 10 ],
                 [ ('x') x 10 ],
                 [ ('x') x 10 ],
                 [ ('x') x 10 ]);
}

sub new_per_loop {
    my @two_d;
    for (0..4){
        my @inner = ('x') x 10;
        push @two_d, \@inner;
    }
}

sub anon_ref_per_loop {
    my @two_d;
    for (0..4){
        push @two_d, [ ('x') x 10 ];
    }
}

sub nested {
    my @two_d;
    for my $i (0..4){
        for my $j (0..9){
            $two_d[$i][$j] = 'x';
        }
    }
}
cmpthese (10_000, {
                 'Explicit'           => \&explicit,
                 'New Array Per Loop' => \&new_per_loop,
                 'Anon. Ref Per Loop' => \&anon_ref_per_loop,
                 'Nested Loops'       => \&nested,
             }
      );
The above code will print out the following statistics (numbers may be slightly off, of course):
Benchmark: timing 10000 iterations of Anon. Ref Per Loop, Explicit, Nested Loops, New Array Per Loop...
Anon. Ref Per Loop:  2 wallclock secs ( 1.53 usr +  0.00 sys =  1.53 CPU) @ 6535.95/s (n=10000)
Explicit:  1 wallclock secs ( 1.24 usr +  0.00 sys =  1.24 CPU) @ 8064.52/s (n=10000)
Nested Loops:  4 wallclock secs ( 4.01 usr +  0.00 sys =  4.01 CPU) @ 2493.77/s (n=10000)
New Array Per Loop:  2 wallclock secs ( 1.76 usr +  0.00 sys =  1.76 CPU) @ 5681.82/s (n=10000)
                     Rate Nested Loops New Array Per Loop Anon. Ref Per Loop Explicit
Nested Loops       2494/s           --               -56%               -62%     -69%
New Array Per Loop 5682/s         128%                 --               -13%     -30%
Anon. Ref Per Loop 6536/s         162%                15%                 --     -19%
Explicit           8065/s         223%                42%                23%       --

The benchmark first tells us how many iterations of which subroutines it's running. It then tells us how long each method took to run the given number of iterations. Finally, it prints out the statistics table, sorted from slowest to fastest. The Rate column tells us how many iterations each subroutine was able to perform per second. The remaining colums tells us how fast each method was in comparison to each of the other methods. (For example, 'Explicit' was 223% faster than 'Nested Loops', while 'New Array Per Loop' is 13% slower than 'Anon. Ref Per Loop'). From the above, we can see that 'Explicit' is by far the fastest of the four methods. It is, however, only 23% faster than 'Ref Per Loop', which requires far less typing and is much more easily maintainable (if your boss suddenly tells you he'd rather have the two-d array be 20x17, and each cell init'ed to 'X' rather than 'x', which of the two would you rather had been used?).

You can, of course, read more about this module, and see its other options, by reading: perldoc Benchmark

Command-line options
Perl provides several command-line options which make it possible to write very quick and very useful "one-liners". For more information on all the options available, refer to perldoc perlrun
-e
This option takes a string and evaluates the Perl code within. This is the primary means of executing a one-liner
 
perl -e'print qq{Hello World\n};'
(In windows, you may have to use double-quotes rather than single. Either way, it's probably better to use q// and qq// within your one liner, rather than remembering to escape the quotes).
-l
This option has two distinct effects that work in conjunction. First, it sets $\ (the output record terminator) to the current value of $/ (the input record separator). In effect, this means that every print statement will automatically have a newline appended. Secondly, it auto-chomps any input read via the <> operator, saving you the typing necessary to do it.
 
perl -le 'while (<>){ $_ .= q{testing};  print; }'
The above would automatically chomp $_, and then add the newline back on at the print statement, so that "testing" appears on the same line as the entered string.
-w
This is the standard way to enable warnings in your one liners. This saves you from having to type use warnings;
-M
This option auto-uses a given module.
 
perl -MData::Dumper -le'my @foo=(1..10); print Dumper(\@foo);'
-n
This disturbingly powerful option wraps your entire one-liner in a while (<>) { ... } loop. That is, your one-liner will be executed once for each line of each file specified on the command line, each time setting $_ to the current line and $. to current line number.
 
perl -ne 'print if /^\d/' foo.txt beta.txt
The above one-line of code would loop through foo.txt and beta.txt, printing out all the lines that start with a digit. ($_ is assigned via the implicit while (<>) loop, and both print and m// operate on $_ if an explict argument isn't given).
-p
This is essentially the same thing as -n, except that it places a continue { print; } block after the while (<>) { ... } loop in which your code is wrapped. This is useful for reading through a list of files, making some sort of modification, and printing the results.
 
perl -pe 's/Paul/John/' email.txt
Open the file email.txt, loop through each line, replacing any instance of "Paul" with "John", and print every line (modified or not) to STDOUT
-i
This one sometimes astounds people that such a thing is possible with so little typing. -i is used in conjunction with either -n or -p. It causes the files specified on the command line to be edited "in-place", meaning that while you're looping through the lines of the files, all print statements are directed back to the original files. (That goes for both explicit prints, as well as the print in the continue block added by -p.)
If you give -i a string, this string will be used to create a back-up copy of the original file. Like so:
 
perl -pi.bkp -e's/Paul/John/' email.txt msg.txt
The above opens email.txt, replaces each line's instance of "Paul" with "John", and prints the results back to email.txt. The original email.txt is saved as email.txt.bkp. The same is then done for msg.txt

Remember that any of the command-line options listed here can also be given at the end of the shebang in non-oneliners. (But please do not start using -w in your real programs - use warnings; is still preferred because of its lexical scope and configurability).

Data::Dumper
The standard Data::Dumper module is very useful for examining exactly what is contained in your data structure (be it hash, array, or object (when we come to them) ). When you use this module, it exports one function, named Dumper. This function takes a reference to a data structure and returns a nicely formatted description of what that structure contains.
#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;

my @foo = (5..10);
#add one element to the end of the array
#do you see the error?
$foo[@foo+1] = 'last';

print Dumper(\@foo);

When run, this program shows you exactly what is inside @foo:

$VAR1 = [
          5,
          6,
          7,
          8,
          9,
          10,
          undef,
          'last'
        ];

(I know we haven't covered references yet. For now, just accept my assertion that you create a reference by prepending the variable name with a backslash...)

__DATA__ & <DATA>
Perl uses the __DATA__ marker as a pseudo-datafile. You can use this marker to write quick tests which would involve finding a file name, opening that file, and reading from that file. If you just want to test a piece of code that requires a file to be read (but don't want to test the actual file opening and reading), place the data that would be in the input file under the __DATA__ marker. You can then read from this pseudo-file using <DATA>, without bothering to open an actual file:
#!/usr/bin/env perl
use strict;
use warnings;

while (my $line = <DATA>) {
  chomp $line;
  print "Size of line $.:  ", length $line, "\n";
}

__DATA__
hello world
42
abcde

The above program would print:

Size of line 1: 11
Size of line 2: 2
Size of line 3: 5
$.
The $. variable keeps track of the line numbers of the file currently being processed via a while (<$fh>) { ... } loop. More explicitly, it is the number of the last line read of the last file read.
__FILE__ & __LINE__
These are two special markers that return, respectively, the name of the file Perl is currently executing, and the Line number where it resides. These can be used in your own debugging statements, to remind yourself where your outputs were in the source code:
  print "On line " . __LINE__ . " of file " . __FILE__ . ", \$foo = $foo\n";
    

Note that neither of these markers are variables, so they cannot be interpolated in a double-quoted string

warn() & die()
These are the most basic of all debugging techniques. warn() takes a list of strings, and prints them to STDERR. If the last element of the list does not end in a newline, warn() will also print the current filename and line number on which the warning occurred. Execution then proceeds as normal.

die() is identical to warn(), with one major exception - the program exits after printing the list of strings.

All debugging statements should make use of either warn() or die() rather than print(). This will insure you see your debugging output even if STDOUT has been redirected, and will give you the helpful clues of exactly where in your code the warning occurred.

Antibugging in Perl 7 Tips for Reducing Complexity

"Complexity is the enemy, and our aim is to kill it."
-Jan Baan

One of Perl's greatest strengths is its expressiveness and extreme conciseness. Complexity is the bane of software development: when a program grows beyond a certain size, it becomes much harder to test, maintain, read, or extend. Unfortunately, today's problems mean this is true for every program we need. Anything you can do to minimize the complexity of your program will pay handsome dividends.

The complexity of a program is a function of several factors:

Whenever a language allows you to change some code to reduce any of these factors, you reduce complexity.

Komodo 3.1 - Online Docs Debugging Perl Debugging Perl Remotely

When debugging a Perl program remotely, the program is executed on the remote system and the debug output is sent to Komodo. Komodo controls the debugging session (e.g. stepping and breakpoints) once the session starts on the remote system.

Perl remote debugging works on any system that can run the version of perl5db.pl distributed with Komodo. ActivePerl and most other distributions of Perl (version 5.6 or greater) will work.

Note: If you have the ActiveState Perl Development Kit (PDK) installed, follow the instructions for PDK users to disable the PDK debugger before continuing.

To debug Perl programs remotely:

Step One: Configure the Remote Machine

  1. Log in to the remote machine.

     
  2. Copy Komodo's perl debugger and its associated libraries to the remote machine by copying the entire dbgp/perllib sub-directory of the Komodo installation to the new machine, or download a package from the Komodo Remote Debugging page.

    Note: Do not copy perl5db.pl to the Perl "lib" directory on the remote machine, as this will overwrite the standard perl5db.pl file.

     
  3. On the remote machine, set the PERL5LIB environment variable to the location of the new perl5db.pl and its libraries. For example, if the remote machine is running Windows and perllib directory was copied to C:\misc\perllib, set the variable as follows:
    set PERL5LIB=C:\misc\perllib

    For example, if the remote machine is running Linux and perllib was copied to the /home/me/perl/komodo_perl_debugging directory, set the variable as follows:

    export PERL5LIB=/home/me/perl/komodo_perl_debugging/perllib
  4. On the remote machine, set the PERLDB_OPTS and DBGP_IDEKEY variables. This tells the Perl interpreter on the remote machine where to connect to Komodo or the DBGP Proxy and how to identify itself.

     
    	PERLDB_OPTS=RemotePort=<hostname>:<port>
    	DBGP_IDEKEY=<ide_key>
    
    • The port number must match the port number specified in Edit|Preferences|Debugger. Click Debug|Listener Status to check the current port.
    • Replace <hostname> with the name or IP address of the machine running Komodo.
    • If DBGP_IDEKEY is unset, the USER or USERNAME environment variable is used as the IDE Key.
    • The variable definitions must be on one line.

     

    For example:
     

    Windows 2000, NT, XP

    	set PERLDB_OPTS=RemotePort=127.0.0.1:9000
    	set DBGP_IDEKEY=jdoe
    

    Windows Me

    Use the MSCONFIG utility (Start|Run|MSCONFIG). Select the Environment tab, and create a new variable with the Variable Name of PERLDB_OPTS, and the Variable Value of RemotePort=127.0.0.1:9000.

    Unix Systems

    	export PERLDB_OPTS="RemotePort=127.0.0.1:9000"
    	export DBGP_IDEKEY="jdoe"
    

Step Two: Listen for Remote Debugger

In Komodo, on the Debug menu, click Listen for Remote Debugger.

Step Three: Start the Perl Program on the Remote Machine

Start the debugging process using the "-d" flag:

perl -d program_name.pl

A Perl Debug tab is displayed in Komodo.

Step Four: Debug the Perl Program using Komodo

Use 'F11' to Step In, or 'F5' (Go) to run to the first breakpoint. See Komodo Debugger Functions for full instructions on using Komodo's debugging functionality.

 

Disabling and Enabling the Perl Dev Kit (PDK) Debugger

If you have installed the ActiveState Perl Development Kit (PDK) on the remote machine, the system may be configured to use the PDK debugger when a Perl debug session (perl -d) is launched. To use Komodo's debugger, disable the PDK debugger on the remote machine first. If necessary, you can re-enable the PDK debugger on the remote machine later.

Disabling the PDK Debugger on the Remote Machine

To disable the PDK debugger on the remote machine, perform one of the following three procedures:

Option 1: (Windows and Unix)

At the command shell, enter the following command (depending on your operating system):

Windows

  set PERL5DB=BEGIN { require 'perl5db.pl'; }

Unix

  export PERL5DB="BEGIN { require 'perl5db.pl'; }"

To re-enable the PDK debugger, set the PERL5DB variable to an empty string.

Option 2: (Windows)

  1. Right-click the My Computer icon and select Properties.
  2. Click the Advanced tab.
  3. Click Environment Variables.
  4. In the System variables section, click New.
  5. Set the Variable Name field to PERL5DB.
  6. Set the Variable Value field to BEGIN { require 'perl5db.pl'}.
  7. Click OK three times to exit.

These changes take effect only in new DOS windows. To re-enable the PDK debugger, delete the PERL5DB variable.

Option 3: (Windows)

Change the registry setting for HKEY_LOCAL_MACHINE\SOFTWARE\Perl. Rename the variable PERL5DB to xPERL5DB.

Warning: This registry setting is semi-permanent and persists through machine restarts.

This change takes effect only in new DOS windows. To re-enable the PDK debugger, rename the xPERL5DB registry variable back to PERL5DB.

Configuring Perl for CGI Debugging

Debugging CGI programs on live production servers can seriously impair performance. We recommend using a test server for CGI debugging. Instructions for configuring Microsoft IIS and Apache (Unix) servers are shown below; for other web servers, use these examples and the web server software documentation as a guide for modifying the server environment.

The settings and paths listed are examples only. Substitute these with the specific paths, hostnames and port numbers of your server as necessary

perlcast.com » Interview 14 - Richard Foley

Richard: Being able to interactively work with your code is a very powerful mechanism, really. Because, you can just experiment on the fly with all sort of constructs. You know, simple constructs, or things like when you’re unsure about how somethings evaluates in a list context, or scalar context, or whether it is a list or scalar context. So you can just experiment and find out.

Josh: Okay, so on the subject of the book, you divided into three primary sections. The first being a general overview of the debugger, the second takes you through usage scenarios and customizing the debugger, and the final is a reference section. So, I was just wondering why you chose to layout the book in this way.

Richard: It seemed a fairly natural spread for me, I think, I was hoping that the book would be able to appeal to both people that hadn’t really used the debugger before, hadn’t really had much experience in, and therefore the first several chapters are completely oriented toward the beginner. If you are a more experienced Perl user and, quite possibly, already a debugger user, but you weren’t sure of all the details, then that is where middle of the book was going to come more into effect, to get you up to speed there, really. And of course you need to have a reference, and every books have references, goodness me. The debugger command, well, there’s quite lot of them really, especially the options. We needed to have some form of definitive reference of all the various command possibilities and the various syntaxes. Which, while they are multiplely intuitive, some of them can be a bit obscure, especially when you get down to the options. You need to have the absolutely right name in
some places. So, you sort of need to know where to look and that’s where the online help, again, comes into hand there. In the debugger itself, there is a small screen, a help screen, that you can use. That you can bring up just with a simple “h” command at the prompt. And that gives you almost all the information you need to know at that point. To get more information, you would use “h” and then the command name itself.

Josh: You covered debugging modules and debugging objects separately in the book, and it seems like those two areas kind of overlap some in Perl because of the very loose object definitions. So, what is the difference when you’re debugging those?

Richard: Essentially, a module is just a library. We’ve come to associate object oriented programming with little modules, but the two aren’t strictly bound together in that way. I think treating a number of libraries as a debuggable entity is valid on its own, and there are things the debugger can help you with there. Equally when you use object oriented code it’s entirely irrelevant whether you are actually using modules or you just got a whole bundle of code in a single file. You can still set up inheritance and member variables, classes and so on. And the debugger offers you certain commands to help you with your object oriented programming as well, like the “i” command, which just tells you a little bit about the inheritance of the object you’re looking at. Or rather the executable statement you’ve got in front of you, but you would normally use it on an object.

Josh: Whenever I debug CGI scripts, typically I just print out to the screen and run them through the web browser, or something. So, you can actually debug [CGI scripts using, or] Perl CGI scripts, using the Perl debugger, but it does seem like it been a little bit tricky, if not impossible, honestly to me. So how would you go about doing that?

Richard: The debugger is a very useful tool when you are dealing with CGI scripts, just like any other Perl program. There’s no particular magic there. You would just call your CGI script using “-d,” where appropriate, at the end of the Perl path, and the debugger kicks in, takes control of the situation and offers you a prompt. The point where it gets tricky is if you are using Apache mod_perl, for example, where you are combining with a web server and you’ve got the debugger essentially already sitting inside, well Perl, already sitting inside C space, inside the web server. Even there, thanks to Doug MacEachern’s work with the mod_perl code, Pierce provided a very simple interface which you can effectively switch on, and you can step inside mod_perl, as well. All you have to do is you have to get the server running in single user mode, and there’s a small configuration file change you have to make in the Apache server config file. And then you can step through mod_perl programs, j
ust like you can step through any other Perl programs. So, it’s very, very sweet, and very, very, simple. It’s not complicated at all. The only complicated about it is trying it the first time. And once you have done that you think “Oh, it’s so easy, why didn’t I do this before.” And that’s the case over and over again I found that with the debugger. That people always where saying “isn’t it complicated” or “isn’t it strange,” you know, and “how can you possibly do this and do that.” And it basically just makes your live much, much easier and much more straightforward. It’s a very powerful tool that people seem to miss because it’s essentially unfamiliar.

I was at one job here in Germany where there were some people on a programming team here that spent, I think probably months of man-hours, well maybe weeks. They were trying to get a tracing mechanism in their moderately complicated Perl code, and they were using caller all the time to essentially step in all the time and print out stack traces during the runtime execution of their program. And all of this, of course, comes in standard with Perl. You can get stack traces, printing out all the arguments going into subroutines, what the return values are, just with a switch, with the “-t,” inside the Perl debugger. It was an awful lot of work, which would have been completely saved had they bothered to read the documentation, you know. Which isn’t to say that none of us ever don’t like to reinvent every now and then, but that was an lot of work for absolutely nothing. It wasn’t even as good, of course, as the debugger solution.

Josh: Whenever you say “reinventing the wheel,” I am not sure if this is a reinvention or an improvement, or not, but there are some debugger replacements, or at least supplements, that are available, and one of these is “Devel-ebug.” And how does this module actually compare to the Perl debugger?

Richard: I’ve not yet time to recall on this to dive into that a great deal. But I believe that’s Leon’s newer module, or at least I know he has been working on one. And I think any approach to making debugging Perl programs is a good thing. And if there’s several debuggers out there to choose from that can only be a good thing too. There have been various attempts in the past, I think, to replace the debugger, because it is a little bit crusty. It essentially had a bit of a rewrite when Perl 5 came in, and since it has only been extended and extended and extended, and as you can imagine that led to very spaghetti like bundle of code to maintain, which can lead to its own problems. Essentially, any further development tools that we can get our hands on can only be a good thing.

Josh: Is there any GUI to sit on top of the debugger to maybe make it easier for beginning users to use that, other than the command line where you have to remember the commands?

Richard: Yeah, the classic one is probably coming from the UNIX background, is the ptkdb, the Perl/Tk Debugger interface, which works very well with all the Linux platforms. You just have Tk installed and you can run that. And that’s a very mouse oriented debugger interface, and quite friendly. The other one, quite well known, is the Komodo debugger and Perl IDE from ActiveState, which, because I work mostly on UNIX and Linux I don’t have actually much experience with. But from what I have seen of it it’s very sweet. Any of the GUI interfaces that are available. Excellent particularly for CGI debugging. I mean, this is the case where with ptkdb, for example, you can set a display variable where you are using it. A neat little trick is the Perl code that’s running by a web server will send a window to wherever set the display variable to, and you can debug from there. So you can debug from a completely remote machine.

Josh: In the book, you also show how to debug threaded applications and POE based applications. So, what kind of special support does the debugger have to make debugging these types of applications easier?

Richard: Where POE is concerned, really, there is all the extra support needed, because it’s simply a single running application that’s pretending to be threaded, or forked. So it works with that quite happily. Where you are using actual fork calls, and some program do, the debugger does support that. The only problem at hand is setting up a new console. And than you have to a little bit of higgery-pokery to get the correct console running, the correct xterm. The support for forked programs is moderately limited, but it is actually there. What we actually need is for some fork experts to come along, and to write all the various chunks of code to support the debugger on those platforms. The main problem at the moment really is that the Perl debugger is running inside what it thinks is an xterm, and it doesn’t really know how to create more, because you need a new input and output for the debugger itself, not the program as such. There is some minimal support there for forks.

Where threads are concerned, that was a problem until quite recently, because all the variables inside the Perl debugger were being shared among all the threaded programs, and no one really knew which variable was in which thread. And that led to some quite interesting results. But that was fixed quite recently, 5.8.5 I think. And you can now use the Perl debugger with threads as well.

Josh: One feature of the debugger that looks really neat was the ability to debug regular expressions. But before we dive into that, a non-debugger related tip for working with regexes was to avoid contracting the “Leaning Toothpick Syndrome,” and what is that, and how do I avoid it?

Richard: Right, Leaning Toothpick Syndrome is when you normally have a regexp, you normally start with a forward slash and then you end with a forward slash. And so, if you got any forward slash in your regex, like for example in a typical path name on a UNIX like system, it can get very confusing very quickly, which is the start slash and which is the end slash, and which is the slash in the middle, and has it been backslashed yet to escape it. If you just use different delimiters at the end, maybe a comment mark or open and close brackets or braces, that can make the regex a lot easier to read. And then you don’t have to backslash your forward slashes any more, and you no longer get the Leaning Toothpick Syndrome. So when you just have so many forward slashes and backslashes to try to keep them in sync, it get very bitterly confusing.

Josh: Regular expression debugging seem to produce a lot of data, but then again regexes are almost miniature programs within your script. So, what types of information and controls does the debugger provide for regular expressions?

Richard: The debugger itself doesn’t actually provide terribly much regex support itself. It uses what support there is in Perl already. Perl has its own regex engine, that will give you a lot of information if you ask it correctly. It seemed moderately relevant to include a chapter on this in the book, because there was so little information about it anywhere else, and people do have problems with their regexes. So it’s nice to see one thing exploded. Essentially, you’ve got a couple of choices with regexes. You can use the re pragma, use regular expression module then or pragma (use re), which will show you what Perl is going to be doing, or show you what the regex engine is going to be doing in terms of compiling and optimizing your regex. Or you can use the debugging flags. You have to use -Dr for that. But for that you need to have a special Perl build with debugging support, which, agai
n, is not very complicated and shared to do that in the book. But its one more step you have to go through. But its quite nice to see your rexex actually exploded out, and walk through step by step.

Josh: When do I just use the print statement and when do I pull out the debugger? Is there something to look for, some kind of signals, to know that its time to actually invoke the debugger and get beyond the print?

Richard: If you don’t turn around and just use it first off because its a convenient and a close friend, then yeah, you probably gonna be, maybe, at a stage where you are struggling with the print command. When you are saying something like “that just can’t be right,” and you are going round and round in circles, looking at data that is clearly not what you’re expecting. And that really is a time when you should stop and say “Okay, I’m gonna step back and I’m just gonna force myself to go in there, to step inside the code, and to step through it and find out what the values of these variables actually are at the time, rather than assuming there are something of.” And the debugger can help you do that. The nice thing about it is that it can do it without you actually altering your code in any way. One of the problems is, very often people will actually try to find a bug and help fix it. Finding it has involved, perhaps, change in the code in numerous place
s to put printstatements in, and then fixing it involves changing the code again and taking all that print statements out correctly, without affecting aversely, in any way, the running of the program. Sounds very straightforward, but I have seen a number of bugs appear just by people finding and fixing bugs actually introduce their own. And the debugger can help there, with just keeping you slightly arms-length. You are not changing the code in any way. You have complete control of what you are doing.

Josh: That was all the questions I had. Is there anything in the book that you think is really important that we should let people know about?

Richard: I think the last comment is a critical one: Don’t change the source code. Don’t change the code, just get in there and run your program and have a look around as it’s running. It is a very powerful mechanism, and it’s a very convenient mechanism. And it’s a lot of fun as well.

Josh: Thank you. Well, the book is “Pro Perl Debugging.” It’s published by Apress, and is written by Richard Foley, who we’ve been talking to here on Perlcast. Richard, thank you very much for the interview.

Slashdot Pro Perl Debugging

This title was published in hardcover in March 2005 by Apress, a relatively new member of the technical publishing world. The publisher has a Web page for the book that includes links to all of the source code in a Zip file, the table of contents in PDF format, and a form for submitting errata. The book comprises 269 pages, the majority of which are organized into 16 chapters:

 Introduction (not to be confused with the true Introduction immediately preceding it),

11. Using the perl Debugger

Open Perl IDE - User Manual

This section explains how to use Open Perl IDE for debugging.

Important: Open Perl IDE is not able to debug any scripts, if it does not know a path to "perl.exe". If the PATH environment variable contains a valid location, then "perl.exe" will be detected automatically. Otherwise it is necessary to enter a valid location into the "Preferences | General | Directories | Path to perl.exe" field.

There are two methods to debug a script:
  After execution is stopped, it is possible to analyse the actual state of the script by
  Furthermore, it is possible to set/delete breakpoints (see section 5.1 Breakpoints) or to continue/abort the execution of the script. The following table shows the different navigation possibilities:

Table: Debug Navigation
 
Name Shortcut Description
Run F9 Start/Continue script execution until next breakpoint is reached.
Step Over F8 Execute the current script line, not tracing into subroutines.
Step Into F7 Execute the next command in the current script line, tracing into subroutines.
Abort CTRL-F2 Request termination of debug session.
Force Termination CTRL-ALT-F12 Immediately terminate debug session.
You should only use "Force Termination" if you see no other way to stop script execution. Dont't expect Open Perl IDE to work correctly after using forced termination !

If script execution has finished, then Open Perl IDE automatically switches back from debug mode to edit mode.
 

Dr. Dobb's Web Site Code Coverage Analysis in Perl by Brian D Foy

Is all of your Perl code actually executing? Are some statements invoked as expected? The Devel::Coverage module can give you the answer, but you've got to ask the right questions.

Perl comes with a built-in debugging mechanism that allows you to create your own debugger or use one created by someone else. Perl coders can also use the Devel::Coverage debugging module to determine just how much of a program actually executes. This testing process is called coverage analysis. The Devel::Coverage module is available on the Comprehensive Perl Archive Network (CPAN). I'll show you how to use this sort of analysis to actually test all parts of your target program.

You use coverage analysis while testing your code (and everyone tests their code, right?) to ensure that you have done everything that necessary to exercise as much of the code as possible. Proper coverage analysis by itself does not make your code better or your programs bulletproof, but allows you to focus on problems in your code or in the test cases by examining different coverage metrics.

You can use several different coverage analysis

[Nov 2000] Cultured Perl: Debugging Perl with ease. Catch the bugs before they bite by Teodor Zlatanov

Contents:
 The trouble with bugs
 Basic concepts of debugging
 Debugging terms
 The Perl debugger
 Devel::ptkdb
 Writing your own Perl shell
 Building an arsenal of tools
 Resources
 About the author

 

Teodor Zlatanov walks you through both the built-in Perl debugger and CPAN's Devel::ptkdb. The Perl debugger is powerful but frustrating to navigate. CPAN's Devel::ptkdb, on the other hand, works wonders by simplifying code debugging and thereby saving hours of your precious time. In his discussion Zlatanov concentrates on explaining debugging methods and general concepts rather than looking at specific tools.

 

Bugs are as inevitable as death and taxes. Nevertheless, the following material should help you avoid the pitfalls of bugs. Some of the examples will require Perl 5.6.0 or at least 5.005. If you want to try the Emacs examples, you may also need to install the Emacs editor.

 

Recommended Links


In case of broken links please try to use Google search. If you find the page please notify us about new location
Google     

Reference

NAME debug debugger - search.cpan.org

First of all, have you tried using the -w switch? If you're new to the Perl debugger, you may prefer to read perldebtut, which is a tutorial introduction to the debugger .

If you invoke Perl with the -d switch, your script runs under the Perl source debugger. This works like an interactive Perl environment, prompting for debugger commands that let you examine source code, set breakpoints, get stack backtraces, change the values of variables, etc. This is so convenient that you often fire up the debugger all by itself just to test out Perl constructs interactively to see what they do. For example:

    $ perl -d -e 42

In Perl, the debugger is not a separate program the way it usually is in the typical compiled environment. Instead, the -d flag tells the compiler to insert source information into the parse trees it's about to hand off to the interpreter. That means your code must first compile correctly for the debugger to work on it. Then when the interpreter starts up, it preloads a special Perl library file containing the debugger.

The program will halt right before the first run-time executable statement (but see below regarding compile-time statements) and ask you to enter a debugger command. Contrary to popular expectations, whenever the debugger halts and shows you a line of code, it always displays the line it's about to execute, rather than the one it has just executed.

Any command not recognized by the debugger is directly executed (eval'd) as Perl code in the current package. (The debugger uses the DB package for keeping its own state information.)

Note that the said eval is bound by an implicit scope. As a result any newly introduced lexical variable or any modified capture buffer content is lost after the eval. The debugger is a nice environment to learn Perl, but if you interactively experiment using material which should be in the same scope, stuff it in one line.

For any text entered at the debugger prompt, leading and trailing whitespace is first stripped before further processing. If a debugger command coincides with some function in your own program, merely precede the function with something that doesn't look like a debugger command, such as a leading ; or perhaps a +, or by wrapping it with parentheses or braces.

Debugger Commands

The debugger understands the following commands:

h
Prints out a summary help message
h [command]
Prints out a help message for the given debugger command.
h h
The special argument of h h produces the entire help page, which is quite long.

If the output of the h h command (or any command, for that matter) scrolls past your screen, precede the command with a leading pipe symbol so that it's run through your pager, as in

    DB> |h h

You may change the pager which is used via o pager=... command.

p expr
Same as print {$DB::OUT} expr in the current package. In particular, because this is just Perl's own print function, this means that nested data structures and objects are not dumped, unlike with the x command.

The DB::OUT filehandle is opened to /dev/tty, regardless of where STDOUT may be redirected to.

x [maxdepth] expr
Evaluates its expression in list context and dumps out the result in a pretty-printed fashion. Nested data structures are printed out recursively, unlike the real print function in Perl. When dumping hashes, you'll probably prefer 'x \%h' rather than 'x %h'. See Dumpvalue if you'd like to do this yourself.

The output format is governed by multiple options described under "Configurable Options".

If the maxdepth is included, it must be a numeral N; the value is dumped only N levels deep, as if the dumpDepth option had been temporarily set to N.

V [pkg [vars]]
Display all (or some) variables in package (defaulting to main) using a data pretty-printer (hashes show their keys and values so you see what's what, control characters are made printable, etc.). Make sure you don't put the type specifier (like $) there, just the symbol names, like this:
    V DB filename line

Use ~pattern and !pattern for positive and negative regexes.

This is similar to calling the x command on each applicable var.

X [vars]
Same as V currentpackage [vars].
y [level [vars]]
Display all (or some) lexical variables (mnemonic: mY variables) in the current scope or level scopes higher. You can limit the variables that you see with vars which works exactly as it does for the V and X commands. Requires the PadWalker module version 0.08 or higher; will warn if this isn't installed. Output is pretty-printed in the same style as for V and the format is controlled by the same options.
T
Produce a stack backtrace. See below for details on its output.
s [expr]
Single step. Executes until the beginning of another statement, descending into subroutine calls. If an expression is supplied that includes function calls, it too will be single-stepped.
n [expr]
Next. Executes over subroutine calls, until the beginning of the next statement. If an expression is supplied that includes function calls, those functions will be executed with stops before each statement.
r
Continue until the return from the current subroutine. Dump the return value if the PrintRet option is set (default).
<CR>
Repeat last n or s command.
c [line|sub]
Continue, optionally inserting a one-time-only breakpoint at the specified line or subroutine.
l
List next window of lines.
l min+incr
List incr+1 lines starting at min.
l min-max
List lines min through max. l - is synonymous to -.
l line
List a single line.
l subname
List first window of lines from subroutine. subname may be a variable that contains a code reference.
-
List previous window of lines.
v [line]
View a few lines of code around the current line.
.
Return the internal debugger pointer to the line last executed, and print out that line.
f filename
Switch to viewing a different file or eval statement. If filename is not a full pathname found in the values of %INC, it is considered a regex.

evaled strings (when accessible) are considered to be filenames: f (eval 7) and f eval 7\b access the body of the 7th evaled string (in the order of execution). The bodies of the currently executed eval and of evaled strings that define subroutines are saved and thus accessible.

/pattern/
Search forwards for pattern (a Perl regex); final / is optional. The search is case-insensitive by default.
?pattern?
Search backwards for pattern; final ? is optional. The search is case-insensitive by default.
L [abw]
List (default all) actions, breakpoints and watch expressions
S [[!]regex]
List subroutine names [not] matching the regex.
t
Toggle trace mode (see also the AutoTrace option).
t expr
Trace through execution of expr. See "Frame Listing Output Examples" in perldebguts for examples.
b
Sets breakpoint on current line
b [line] [condition]
Set a breakpoint before the given line. If a condition is specified, it's evaluated each time the statement is reached: a breakpoint is taken only if the condition is true. Breakpoints may only be set on lines that begin an executable statement. Conditions don't use if:
    b 237 $x > 30
    b 237 ++$count237 < 11
    b 33 /pattern/i
b subname [condition]
Set a breakpoint before the first line of the named subroutine. subname may be a variable containing a code reference (in this case condition is not supported).
b postpone subname [condition]
Set a breakpoint at first line of subroutine after it is compiled.
b load filename
Set a breakpoint before the first executed line of the filename, which should be a full pathname found amongst the %INC values.
b compile subname
Sets a breakpoint before the first statement executed after the specified subroutine is compiled.
B line
Delete a breakpoint from the specified line.
B *
Delete all installed breakpoints.
a [line] command
Set an action to be done before the line is executed. If line is omitted, set an action on the line about to be executed. The sequence of steps taken by the debugger is
  1. check for a breakpoint at this line
  2. print the line if necessary (tracing)
  3. do any actions associated with that line
  4. prompt user if at a breakpoint or in single-step
  5. evaluate line

For example, this will print out $foo every time line 53 is passed:

    a 53 print "DB FOUND $foo\n"
A line
Delete an action from the specified line.
A *
Delete all installed actions.
w expr
Add a global watch-expression. We hope you know what one of these is, because they're supposed to be obvious.
W expr
Delete watch-expression
W *
Delete all watch-expressions.
o
Display all options
o booloption ...
Set each listed Boolean option to the value 1.
o anyoption? ...
Print out the value of one or more options.
o option=value ...
Set the value of one or more options. If the value has internal whitespace, it should be quoted. For example, you could set o pager="less -MQeicsNfr" to call less with those specific options. You may use either single or double quotes, but if you do, you must escape any embedded instances of same sort of quote you began with, as well as any escaping any escapes that immediately precede that quote but which are not meant to escape the quote itself. In other words, you follow single-quoting rules irrespective of the quote; eg: o option='this isn\'t bad' or o option="She said, \"Isn't it?\"".

For historical reasons, the =value is optional, but defaults to 1 only where it is safe to do so--that is, mostly for Boolean options. It is always better to assign a specific value using =. The option can be abbreviated, but for clarity probably should not be. Several options can be set together. See "Configurable Options" for a list of these.

< ?
List out all pre-prompt Perl command actions.
< [ command ]
Set an action (Perl command) to happen before every debugger prompt. A multi-line command may be entered by backslashing the newlines.
< *
Delete all pre-prompt Perl command actions.
<< command
Add an action (Perl command) to happen before every debugger prompt. A multi-line command may be entered by backwhacking the newlines.
> ?
List out post-prompt Perl command actions.
> command
Set an action (Perl command) to happen after the prompt when you've just given a command to return to executing the script. A multi-line command may be entered by backslashing the newlines (we bet you couldn't've guessed this by now).
> *
Delete all post-prompt Perl command actions.
>> command
Adds an action (Perl command) to happen after the prompt when you've just given a command to return to executing the script. A multi-line command may be entered by backslashing the newlines.
{ ?
List out pre-prompt debugger commands.
{ [ command ]
Set an action (debugger command) to happen before every debugger prompt. A multi-line command may be entered in the customary fashion.

Because this command is in some senses new, a warning is issued if you appear to have accidentally entered a block instead. If that's what you mean to do, write it as with ;{ ... } or even do { ... }.

{ *
Delete all pre-prompt debugger commands.
{{ command
Add an action (debugger command) to happen before every debugger prompt. A multi-line command may be entered, if you can guess how: see above.
! number
Redo a previous command (defaults to the previous command).
! -number
Redo number'th previous command.
! pattern
Redo last command that started with pattern. See o recallCommand, too.
!! cmd
Run cmd in a subprocess (reads from DB::IN, writes to DB::OUT) See o shellBang, also. Note that the user's current shell (well, their $ENV{SHELL} variable) will be used, which can interfere with proper interpretation of exit status or signal and coredump information.
source file
Read and execute debugger commands from file. file may itself contain source commands.
H -number
Display last n commands. Only commands longer than one character are listed. If number is omitted, list them all.
q or ^D
Quit. ("quit" doesn't work for this, unless you've made an alias) This is the only supported way to exit the debugger, though typing exit twice might work.

Set the inhibit_exit option to 0 if you want to be able to step off the end the script. You may also need to set $finished to 0 if you want to step through global destruction.

R
Restart the debugger by exec()ing a new session. We try to maintain your history across this, but internal settings and command-line options may be lost.

The following setting are currently preserved: history, breakpoints, actions, debugger options, and the Perl command-line options -w, -I, and -e.

|dbcmd
Run the debugger command, piping DB::OUT into your current pager.
||dbcmd
Same as |dbcmd but DB::OUT is temporarily selected as well.
= [alias value]
Define a command alias, like
    = quit q

or list current aliases.

command
Execute command as a Perl statement. A trailing semicolon will be supplied. If the Perl statement would otherwise be confused for a Perl debugger, use a leading semicolon, too.
m expr
List which methods may be called on the result of the evaluated expression. The expression may evaluated to a reference to a blessed object, or to a package name.
M
Displays all loaded modules and their versions
man [manpage]
Despite its name, this calls your system's default documentation viewer on the given page, or on the viewer itself if manpage is omitted. If that viewer is man, the current Config information is used to invoke man using the proper MANPATH or -M manpath option. Failed lookups of the form XXX that match known manpages of the form perlXXX will be retried. This lets you type man debug or man op from the debugger.

On systems traditionally bereft of a usable man command, the debugger invokes perldoc. Occasionally this determination is incorrect due to recalcitrant vendors or rather more felicitously, to enterprising users. If you fall into either category, just manually set the $DB::doccmd variable to whatever viewer to view the Perl documentation on your system. This may be set in an rc file, or through direct assignment. We're still waiting for a working example of something along the lines of:

    $DB::doccmd = 'netscape -remote http://something.here/';

Configurable Options

The debugger has numerous options settable using the o command, either interactively or from the environment or an rc file. (./.perldb or ~/.perldb under Unix.)

recallCommand, ShellBang
The characters used to recall command or spawn shell. By default, both are set to !, which is unfortunate.
pager
Program to use for output of pager-piped commands (those beginning with a | character.) By default, $ENV{PAGER} will be used. Because the debugger uses your current terminal characteristics for bold and underlining, if the chosen pager does not pass escape sequences through unchanged, the output of some debugger commands will not be readable when sent through the pager.
tkRunning
Run Tk while prompting (with ReadLine).
signalLevel, warnLevel, dieLevel
Level of verbosity. By default, the debugger leaves your exceptions and warnings alone, because altering them can break correctly running programs. It will attempt to print a message when uncaught INT, BUS, or SEGV signals arrive. (But see the mention of signals in BUGS below.)

To disable this default safe mode, set these values to something higher than 0. At a level of 1, you get backtraces upon receiving any kind of warning (this is often annoying) or exception (this is often valuable). Unfortunately, the debugger cannot discern fatal exceptions from non-fatal ones. If dieLevel is even 1, then your non-fatal exceptions are also traced and unceremoniously altered if they came from eval'd strings or from any kind of eval within modules you're attempting to load. If dieLevel is 2, the debugger doesn't care where they came from: It usurps your exception handler and prints out a trace, then modifies all exceptions with its own embellishments. This may perhaps be useful for some tracing purposes, but tends to hopelessly destroy any program that takes its exception handling seriously.

AutoTrace
Trace mode (similar to t command, but can be put into PERLDB_OPTS).
LineInfo
File or pipe to print line number info to. If it is a pipe (say, |visual_perl_db), then a short message is used. This is the mechanism used to interact with a slave editor or visual debugger, such as the special vi or emacs hooks, or the ddd graphical debugger.
inhibit_exit
If 0, allows stepping off the end of the script.
PrintRet
Print return value after r command if set (default).
ornaments
Affects screen appearance of the command line (see Term::ReadLine). There is currently no way to disable these, which can render some output illegible on some displays, or with some pagers. This is considered a bug.
frame
Affects the printing of messages upon entry and exit from subroutines. If frame & 2 is false, messages are printed on entry only. (Printing on exit might be useful if interspersed with other messages.)

If frame & 4, arguments to functions are printed, plus context and caller info. If frame & 8, overloaded stringify and tied FETCH is enabled on the printed arguments. If frame & 16, the return value from the subroutine is printed.

The length at which the argument list is truncated is governed by the next option:

maxTraceLen
Length to truncate the argument list when the frame option's bit 4 is set.
windowSize
Change the size of code list window (default is 10 lines).

The following options affect what happens with V, X, and x commands:

arrayDepth, hashDepth
Print only first N elements ('' for all).
dumpDepth
Limit recursion depth to N levels when dumping structures. Negative values are interpreted as infinity. Default: infinity.
compactDump, veryCompact
Change the style of array and hash output. If compactDump, short array may be printed on one line.
globPrint
Whether to print contents of globs.
DumpDBFiles
Dump arrays holding debugged files.
DumpPackages
Dump symbol tables of packages.
DumpReused
Dump contents of "reused" addresses.
quote, HighBit, undefPrint
Change the style of string dump. The default value for quote is auto; one can enable double-quotish or single-quotish format by setting it to " or ', respectively. By default, characters with their high bit set are printed verbatim.
UsageOnly
Rudimentary per-package memory usage dump. Calculates total size of strings found in variables in the package. This does not include lexicals in a module's file scope, or lost in closures.

After the rc file is read, the debugger reads the $ENV{PERLDB_OPTS} environment variable and parses this as the remainder of a "O ..." line as one might enter at the debugger prompt. You may place the initialization options TTY, noTTY, ReadLine, and NonStop there.

If your rc file contains:

  parse_options("NonStop=1 LineInfo=db.out AutoTrace");

then your script will run without human intervention, putting trace information into the file db.out. (If you interrupt it, you'd better reset LineInfo to /dev/tty if you expect to see anything.)

TTY
The TTY to use for debugging I/O.
noTTY
If set, the debugger goes into NonStop mode and will not connect to a TTY. If interrupted (or if control goes to the debugger via explicit setting of $DB::signal or $DB::single from the Perl script), it connects to a TTY specified in the TTY option at startup, or to a tty found at runtime using the Term::Rendezvous module of your choice.

This module should implement a method named new that returns an object with two methods: IN and OUT. These should return filehandles to use for debugging input and output correspondingly. The new method should inspect an argument containing the value of $ENV{PERLDB_NOTTY} at startup, or "$ENV{HOME}/.perldbtty$$" otherwise. This file is not inspected for proper ownership, so security hazards are theoretically possible.

ReadLine
If false, readline support in the debugger is disabled in order to debug applications that themselves use ReadLine.
NonStop
If set, the debugger goes into non-interactive mode until interrupted, or programmatically by setting $DB::signal or $DB::single.

Here's an example of using the $ENV{PERLDB_OPTS} variable:

    $ PERLDB_OPTS="NonStop frame=2" perl -d myprogram

That will run the script myprogram without human intervention, printing out the call tree with entry and exit points. Note that NonStop=1 frame=2 is equivalent to N f=2, and that originally, options could be uniquely abbreviated by the first letter (modulo the Dump* options). It is nevertheless recommended that you always spell them out in full for legibility and future compatibility.

Other examples include

    $ PERLDB_OPTS="NonStop LineInfo=listing frame=2" perl -d myprogram

which runs script non-interactively, printing info on each entry into a subroutine and each executed line into the file named listing. (If you interrupt it, you would better reset LineInfo to something "interactive"!)

Other examples include (using standard shell syntax to show environment variable settings):

  $ ( PERLDB_OPTS="NonStop frame=1 AutoTrace LineInfo=tperl.out"
      perl -d myprogram )

which may be useful for debugging a program that uses Term::ReadLine itself. Do not forget to detach your shell from the TTY in the window that corresponds to /dev/ttyXX, say, by issuing a command like

  $ sleep 1000000

See "Debugger Internals" in perldebguts for details.

Debugger input/output

Prompt
The debugger prompt is something like
    DB<8>

or even

    DB<<17>>

where that number is the command number, and which you'd use to access with the built-in csh-like history mechanism. For example, !17 would repeat command number 17. The depth of the angle brackets indicates the nesting depth of the debugger. You could get more than one set of brackets, for example, if you'd already at a breakpoint and then printed the result of a function call that itself has a breakpoint, or you step into an expression via s/n/t expression command.

Multiline commands
If you want to enter a multi-line command, such as a subroutine definition with several statements or a format, escape the newline that would normally end the debugger command with a backslash. Here's an example:
      DB<1> for (1..4) {         \
      cont:     print "ok\n";   \
      cont: }
      ok
      ok
      ok
      ok

Note that this business of escaping a newline is specific to interactive commands typed into the debugger.

Stack backtrace
Here's an example of what a stack backtrace via T command might look like:
    $ = main::infested called from file `Ambulation.pm' line 10
    @ = Ambulation::legs(1, 2, 3, 4) called from file `camel_flea' line 7
    $ = main::pests('bactrian', 4) called from file `camel_flea' line 4

The left-hand character up there indicates the context in which the function was called, with $ and @ meaning scalar or list contexts respectively, and . meaning void context (which is actually a sort of scalar context). The display above says that you were in the function main::infested when you ran the stack dump, and that it was called in scalar context from line 10 of the file Ambulation.pm, but without any arguments at all, meaning it was called as &infested. The next stack frame shows that the function Ambulation::legs was called in list context from the camel_flea file with four arguments. The last stack frame shows that main::pests was called in scalar context, also from camel_flea, but from line 4.

If you execute the T command from inside an active use statement, the backtrace will contain both a require frame and an eval) frame.

Line Listing Format
This shows the sorts of output the l command can produce:
    DB<<13>> l
  101:                @i{@i} = ();
  102:b               @isa{@i,$pack} = ()
  103                     if(exists $i{$prevpack} || exists $isa{$pack});
  104             }
  105
  106             next
  107==>              if(exists $isa{$pack});
  108
  109:a           if ($extra-- > 0) {
  110:                %isa = ($pack,1);

Breakable lines are marked with :. Lines with breakpoints are marked by b and those with actions by a. The line that's about to be executed is marked by ==>.

Please be aware that code in debugger listings may not look the same as your original source code. Line directives and external source filters can alter the code before Perl sees it, causing code to move from its original positions or take on entirely different forms.

Frame listing
When the frame option is set, the debugger would print entered (and optionally exited) subroutines in different styles. See perldebguts for incredibly long examples of these.

Debugging compile-time statements

If you have compile-time executable statements (such as code within BEGIN and CHECK blocks or use statements), these will not be stopped by debugger, although requires and INIT blocks will, and compile-time statements can be traced with AutoTrace option set in PERLDB_OPTS). From your own Perl code, however, you can transfer control back to the debugger using the following statement, which is harmless if the debugger is not running:

    $DB::single = 1;

If you set $DB::single to 2, it's equivalent to having just typed the n command, whereas a value of 1 means the s command. The $DB::trace variable should be set to 1 to simulate having typed the t command.

Another way to debug compile-time code is to start the debugger, set a breakpoint on the load of some module:

    DB<7> b load f:/perllib/lib/Carp.pm
  Will stop on load of `f:/perllib/lib/Carp.pm'.

and then restart the debugger using the R command (if possible). One can use b compile subname for the same purpose.

Debugger Customization

The debugger probably contains enough configuration hooks that you won't ever have to modify it yourself. You may change the behaviour of debugger from within the debugger using its o command, from the command line via the PERLDB_OPTS environment variable, and from customization files.

You can do some customization by setting up a .perldb file, which contains initialization code. For instance, you could make aliases like these (the last one is one people expect to be there):

    $DB::alias{'len'}  = 's/^len(.*)/p length($1)/';
    $DB::alias{'stop'} = 's/^stop (at|in)/b/';
    $DB::alias{'ps'}   = 's/^ps\b/p scalar /';
    $DB::alias{'quit'} = 's/^quit(\s*)/exit/';

You can change options from .perldb by using calls like this one;

    parse_options("NonStop=1 LineInfo=db.out AutoTrace=1 frame=2");

The code is executed in the package DB. Note that .perldb is processed before processing PERLDB_OPTS. If .perldb defines the subroutine afterinit, that function is called after debugger initialization ends. .perldb may be contained in the current directory, or in the home directory. Because this file is sourced in by Perl and may contain arbitrary commands, for security reasons, it must be owned by the superuser or the current user, and writable by no one but its owner.

You can mock TTY input to debugger by adding arbitrary commands to @DB::typeahead. For example, your .perldb file might contain:

    sub afterinit { push @DB::typeahead, "b 4", "b 6"; }

Which would attempt to set breakpoints on lines 4 and 6 immediately after debugger initialization. Note that @DB::typeahead is not a supported interface and is subject to change in future releases.

If you want to modify the debugger, copy perl5db.pl from the Perl library to another name and hack it to your heart's content. You'll then want to set your PERL5DB environment variable to say something like this:

    BEGIN { require "myperl5db.pl" }

As a last resort, you could also use PERL5DB to customize the debugger by directly setting internal variables or calling debugger functions.

Note that any variables and functions that are not documented in this document (or in perldebguts) are considered for internal use only, and as such are subject to change without notice.

Readline Support

As shipped, the only command-line history supplied is a simplistic one that checks for leading exclamation points. However, if you install the Term::ReadKey and Term::ReadLine modules from CPAN, you will have full editing capabilities much like GNU readline(3) provides. Look for these in the modules/by-module/Term directory on CPAN. These do not support normal vi command-line editing, however.

A rudimentary command-line completion is also available. Unfortunately, the names of lexical variables are not available for completion.

Editor Support for Debugging

If you have the FSF's version of emacs installed on your system, it can interact with the Perl debugger to provide an integrated software development environment reminiscent of its interactions with C debuggers.

Perl comes with a start file for making emacs act like a syntax-directed editor that understands (some of) Perl's syntax. Look in the emacs directory of the Perl source distribution.

A similar setup by Tom Christiansen for interacting with any vendor-shipped vi and the X11 window system is also available. This works similarly to the integrated multiwindow support that emacs provides, where the debugger drives the editor. At the time of this writing, however, that tool's eventual location in the Perl distribution was uncertain.

Users of vi should also look into vim and gvim, the mousey and windy version, for coloring of Perl keywords.

Note that only perl can truly parse Perl, so all such CASE tools fall somewhat short of the mark, especially if you don't program your Perl as a C programmer might.

The Perl Profiler

If you wish to supply an alternative debugger for Perl to run, just invoke your script with a colon and a package argument given to the -d flag. The most popular alternative debuggers for Perl is the Perl profiler. Devel::DProf is now included with the standard Perl distribution. To profile your Perl program in the file mycode.pl, just type:

    $ perl -d:DProf mycode.pl

When the script terminates the profiler will dump the profile information to a file called tmon.out. A tool like dprofpp, also supplied with the standard Perl distribution, can be used to interpret the information in that profile.

Debugging regular expressions

See also Rx, the Perl Regular Expression Debugger

use re 'debug' enables you to see the gory details of how the Perl regular expression engine works. In order to understand this typically voluminous output, one must not only have some idea about how regular expression matching works in general, but also know how Perl's regular expressions are internally compiled into an automaton. These matters are explored in some detail in "Debugging regular expressions" in perldebguts.

Debugging memory usage

Perl contains internal support for reporting its own memory usage, but this is a fairly advanced concept that requires some understanding of how memory allocation works. See "Debugging Perl memory usage" in perldebguts for the details.

You did try the -w switch, didn't you?

perldebtut, perldebguts, re, DB, Devel::DProf, dprofpp, Dumpvalue, and perlrun.

When debugging a script that uses #! and is thus normally found in $PATH, the -S option causes perl to search $PATH for it, so you don't have to type the path or which $scriptname.

  $ perl -Sd foo.pl

Tips

Debugging Tips

The goal is pretty simple: you want your code to work. The current state of affairs is also pretty simple: it ain't working. This note is all about how to get from where you are to where you want to be. In PHENIX, we have all sorts of code. There are interpreted scripts in shell, perl and ROOT macros. There are programs compiled from C, C++ and Fortran source code. There are standalone programs. There are shared libraries. And there are dynamically loaded shared libraries. It's quite a zoo and figuring out what you should do to diagnose the source of a problem when something isn't working properly can be a bit daunting.

I recently gave a presentation about debugging in PHENIX.

Before I start describing specific techniques for debugging code, here is some more general advice.

The long-time favored refuge of those who don't know how to use better techniques. I hope this note will help you learn a few of these better techniques and make the practice of embedding print statements in your code a thing of the past. Is there a place for the print statement in the armamentarium of the serious debugger? Well, yes, but those places are few and far between. Depending on the environment in which you're working, a print statement may be the most sophisticated option at your disposal for debugging distributed programs like those built on  top of MPI (message passing interface). It might be your only option if you're debugging code running on stripped down embedded processors.

You're not debugging code under those conditions. Stop using print statements to debug your code.
 

Script tracing

What's a script? Roughly speaking, it's a piece of code that gets fed to an interpreter whenever you want to use it. It's not quite that simple in real life, but that'll do for now. We have lots of scripting languages. Shell scripts, perl scripts, and ROOT macros are all scripts. There are a few good techniques for debugging scripts. One of the easiest is tracing.

Tracing means telling the interpreter that's handling the script to print out each line of the script before it executes it. The output of the script also gets printed, so you end up with a log of source lines intertwined with script output. It's a bit like embedding a print statement before each and every line of your script. It can result in a lot of undigested information, and sometimes that's enough to track down the reason your script isn't working the way you thought it was supposed to. Tracing, like embedding pring statements, has the downside that it's not very flexible; you're just a passive observer as your script runs and spews its output to the screen. You can't control your program. You can't change the values of any variables. You can' do much of anything excpet watch.  But sometimes that's enough.
 

Tracing shell scripts

Shell scripts are very useful. They must be useful since they come in such a variety of flavors. Among the choices you have are sh, csh, tcsh, ksh, zsh and ash scripts.  They're all similar, yet quirkily different.  Most of the scripts you'll encounter (or write) will be sh or tcsh scripts. You can turn on tracing for these type of scripts (and for some of the others also) by adding the command option "-xv" to the command line of the appropriate interpreter. For instance, suppose you have a tcsh script called dpm.csh that contains the following lines:
 
foreach n (5 2 1 0)
 @ i = 10 / $n   
 echo $i
end

If you run this straight away, you should see this:
 

% tcsh dpm.csh
2
5
10
Division by 0.

OK, there's a bug in the code (but then you knew that). Let's turn on tracing and see if it helps us narrow things down.  Do it like this:
 

% tcsh -xv dpm.csh
foreach n ( 5 2 1 0 )
@ i = 10 / 5
echo 2
2
end
@ i = 10 / 2
echo 5
5
end
@ i = 10 / 1
echo 10
10
end
@ i = 10 / 0
Division by 0.

At least you can see what the script was planning on doing before it actually did it.  You can see the line where the division by zero is being performed, followed by the line which prints an error message to the screen. This is such a simple example that the tracing doesn't really add much, but you should know how to do it. It can help for much more complicated scripts.
 

Tracing perl scripts

There are similar techniques available for tracing a perl script.  Suppose you had a similarly simple perl script called dpm.pl that contained the following lines:
 
foreach $n (5, 2, 1, 0)
  {
    $i = 10 / $n;
    print "$i\n";
  }

Pretty much the same thing as the shell script above. Run it and it produces pretty much the same output too.

% perl dpm.pl
2
5
10
Illegal division by zero at dpm.pl line 2. 

To trace this script, run it under the perl debugger (by adding the "-d" command line option).  At the debugger prompt, type the command "t" to turn on tracing.  Follow that with "r" to run the script and you'll get the tracing output you're looking for. Type "q" to quit the debugger. Like this:

% perl -d dpm.pl
Default die handler restored.

Loading DB routines from perl5db.pl version 1.07
Editor support available.

Enter h or `h h' for help, or `man perldebug' for more help.

main::(dpm.pl:1):	foreach $n (5,2,1,0) {
  DB<1> t
Trace = on
  DB<1> r
main::(dpm.pl:2):	 $i = 10 / $n;
main::(dpm.pl:3):	 print "$i\n";
2
main::(dpm.pl:1):	foreach $n (5,2,1,0) {
main::(dpm.pl:2):	 $i = 10 / $n;
main::(dpm.pl:3):	 print "$i\n";
5
main::(dpm.pl:1):	foreach $n (5,2,1,0) {
main::(dpm.pl:2):	 $i = 10 / $n;
main::(dpm.pl:3):	 print "$i\n";
10
main::(dpm.pl:1):	foreach $n (5,2,1,0) {
main::(dpm.pl:2):	 $i = 10 / $n;
Illegal division by zero at dpm.pl line 2, <IN> line 2.
Debugged program terminated.  Use q to quit or R to restart,
  use O inhibit_exit to avoid stopping after program termination,
  h q, h R or h O to get additional info.  
  DB<1> q

It may look a bit wordy, but it's very much the same thing as you could see when you traced the shell script. It helps you localize the error (it's got something to do with line 2) and that can be very useful in tracking down the cause of the problem.
 

Symbolic Debugging

A symbolic debugger is an extremely useful tool. Trying to develop code without using one is a seriously strange thing to do. A symbolic debugger controls the operation of a running program and is able to show the correspondence between the bit of code the CPU is about to execute and the lines of source code from which that code was compiled. In short, learn how to use a debugger. There is not one single "all singing, all dancing" debugger out there; you may have to learn to work with a couple of different ones, especially if you find yourself working in a variety of different languages. On UNIX-like systems either dbx or gdb (or both) should be available to debug compiled code. I prefer using gdb if it's available (it's the standard debugger on all Linux distributions). The perl interpreter has a built-in debugger. You saw a hint of that before when we traced a perl script. ROOT macros can be debugged using the built-in debugging capabilities of the CINT interpreter.

Most debuggers have a large collection of confusing commands for controlling and examining a running program.  The good news is that for most purposes you really only need to learn a few commands and concepts.
 
  1. breakpoints
  2. run
  3. continue
  4. conditional breakpoints
  5. step
  6. step into
  7. examining variables
     


Copyright © 1996-2009 by Dr. Nikolai Bezroukov. www.softpanorama.org was created as a service to the UN Sustainable Development Networking Programme (SDNP) in the author free time. Submit comments This document is an industrial compilation designed and created exclusively for educational use and is placed under the copyright of the Open Content License(OPL). Site uses AdSense so you need to be aware of Google privacy policy. Original materials copyright belong to respective owners. Quotes are made for educational purposes only in compliance with the fair use doctrine.

Disclaimer:

Last updated: August 15, 2009