Perl Debugger Tutorial

Perl uses a fairly common style of debugger, similiar to many other line-oriented debuggers. To get into the debugger, run the program with the '-d' flag on the command line. Try running testDebugger.pl. The debugger will halt at the first line of code that is to be executed (but will not execute it just yet—this is how the debugger always works: the line it shows is the one that will next be evaluated.) The "h h" command will give you an outline of the available commands. If you want to see more complete documentation, see the official web page: http://www.perldoc.com/perl5.6/pod/perldebug.html

Viewing the program code during execution

The 'l' (list) command has many forms and is used to display "windows" of the program's code (defaults to 10 lines per window). Consecutive use of 'l will show consecutive windows. The '.' command moves the current window back to the next line to be executed. The 'v' option will list the window immediately surrounding the current line. The /pattern/, and ?pattern? commands can be used to move forward and backward through the code to find regular expressions.

Executing code in the debugger

n runs until the next statement (the one immediately following this one in the current file) is about to execute. Note that if the current line is a subroutine call, the debugger won't stop until returning from that subroutine. To stop at the first line of the called subroutine, use the s (single-step) command instead. The r command executes until returning from the current subroutine (i.e., until we pop the activation stack).

Viewing variable values

The p command is just the regular Perl print command, so you can use the normal Perl syntax there. So, suppose your program has a variable named $arg, and an array named @myArr. You can view the values of these variables with

p "arg is $arg and the array is @arr"

Of course, that's a bit wordy for a debugging session, probably you'll just do something like:

p $arg

or

p "@arr"

Breakpoints

One of the most powerful features of most debuggers is their ability to stop at a certain line of code, or to stop when a certain condition is met. The simplest type of breakpoint is via a line number. Suppose we are debugging the file testArgs.pl, and we want to stop as soon as we enter the subroutine "change". We look at the source code with an editor and see that subroutine starts at line 24. We can set the breakpoint via the command

b 24

At any time we can list all of our breakpoints (and actions, but more on that later) via the L command. In this case we'd get the output:

  DB<2> L
testArgs.pl:
 24:        print "In change, the formal parameter is $_[0].\n";
   break if (1)
  DB<2>

Now we can just let the program run via the c (continue) command. The program will stop at the next breakpoint. We get the output:

  DB<2> c
In main, the variable arg is 1 before any subroutine calls.
main::change(testArgs.pl:24):       print "In change, the formal parameter is $_
[0].\n";
  DB<2>

which is right where we wanted to be. You might want to try the v (view) command to view the lines of code immediately surrounding this one, and then use the p command to view the values of variables:

  DB<2> v
21==>   #Notice that the subroutine accesses the parameter directly via the @_ variable.
22      #I.e., it does not place the value in a variable.
23      sub change {
24:b        print "In change, the formal parameter is $_[0].\n";
25:         $_[0] += 1;
26:         print "In change, after adding, the parameter is $_[0].\n";
27      }
28
29      #In this subroutine, we stored the formal parameter in a variable.  The assignment
30      #statement makes a copy, so changes to this variable do not affect the formal
  DB<2> p $_[0]
1
  DB<3> p "@_"
1

An easier way to set a breakpoint at the beginning of a subroutine is to simply provide its name as the argument to the b command:

  DB<1> b change
  DB<2> L
testArgs.pl:
 24:        print "In change, the formal parameter is $_[0].\n";
   break if (1)
  DB<2>

Notice that the L command gives the same output. Again, use the c command to continue to this breakpoint. Now that we are at a breakpoint we can look at the activation (or "traceback" or "callback") stack via the T command. Here that would yield:

  DB<2> c
In main, the variable arg is 1 before any subroutine calls.
main::change(testArgs.pl:24):       print "In change, the formal parameter is $_
[0].\n";
  DB<2> T
. = main::change(1) called from file `testArgs.pl' line 11
  DB<2>

which identifies the line we are at, and how we got here.

An even fancier kind of breakpoint is obtained by specifying a condition. The syntax is the same as above except that we append an extra argument to the b command, a Perl expression that will be evaluated each time the program's execution gets to the breakpoint's line. Only if the expression evaluates to true does the debugger halt there. Let's look at an example. Suppose we run the debugger on the program testDebugger.pl. Upon starting the debugger we want to break at the top of the while loop, but only when our iteration variable $arg has exceeded a value of 5. The following shows how we set this breakpoint condition:

main::(testDebugger.pl:8):      looper();
  DB<1> v
5==>    # This program demonstrates the Perl debugger.
6:      use strict;
7
8:      looper();
9
10      sub looper {
11:         my $arg = 0;
12:         while ($arg < 10) {
13:             ++$arg;
14          }
  DB<1> b 12 ($arg > 5)
  DB<2> c
main::looper(testDebugger.pl:12):           while ($arg < 10) {
  DB<2> p $arg
6
  DB<3>

As you can see, the value of $arg is 6, i.e. greater than 5, when the debugger suspends execution. By the way, we can now explain some of the output we saw from an earlier use of the L command above. Using the L command here yields:

  DB<3> L
testDebugger.pl:
 12:        while ($arg < 10) {
   break if (($arg > 5))
  DB<3>

You can see the break condition for line 12 listed there. Now you can probably understand why when we used L earlier, we had this output (repeated here):

  DB<1> b change
  DB<2> L
testArgs.pl:
 24:        print "In change, the formal parameter is $_[0].\n";
   break if (1)
  DB<2>

The "break if (1)" is showing a condition of "1", i.e. a condition which is always true (since any numeric value other than 0 is considered "true"). Thus that breakpoint will always trigger whenever execution reaches line 24.

Watches

It is very common to want to suspend the program when the value of a variable is changed. The w (watch) command does this. The usual usage is w variableName. Let's go debug testArgs.pl again. This time, at the beginning of the debugging session we do a w $arg and then c (continue) the program. We get this:

  DB<1> w $arg
  DB<2> c
Watchpoint 0:   $arg changed:
        old value:      undef
        new value:      '1'
main::(testArgs.pl:10): print "In main, the variable arg is $arg before any subroutine calls.\n";
  DB<2>

As you can see the first break occurs just after execution of line 9,

my ($arg) = 1;

The value of the variable has changed from "undefined" to 1. Now we'll let the session c (continue) again to get:

  DB<2> c
In main, the variable arg is 1 before any subroutine calls.
In change, the formal parameter is 1.
Watchpoint 0:   $arg changed:
        old value:      '1'
        new value:      '2'
main::change(testArgs.pl:26):       print "In change, after adding, the paramete
r is $_[0].\n";
  DB<2> v
23==>   sub change {
24:         print "In change, the formal parameter is $_[0].\n";
25:         $_[0] += 1;
26:         print "In change, after adding, the parameter is $_[0].\n";
27      }
28
29      #In this subroutine, we stored the formal parameter in a variable.  The assignment
30      #statement makes a copy, so changes to this variable do not affect the formal
31      #parameter, and thus don't affect the actual parameter either.
32      sub change2 {
  DB<2>

The debugger has suspended execution just pas the increment line. Note that this line doesn't even explicitly mention "$arg", but $_[0] is a reference (alias) to that value, so execution suspends. Oh, and yes, you may append conditions to watch commands too.

You can clear watches via the W command. Likewise you can clear breakpoints via the B command. (These are the commands for cygwin's Perl. Canonical Perl uses the d command instead of B. Cygwin's syntax is more consistent.)

Actions

Actions are similar to breakpoints and watches. With an action you can assert that a particular expression is to be evaluated whenever a specified line is executed or a specified subroutine is entered. For example, in debugging testDebugger.pl I could have the debugger print the value of $arg with each iteration of the while loop:

main::(testDebugger.pl:8):      looper();
  DB<1> v
5==>    # This program demonstrates the Perl debugger.
6:      use strict;
7
8:      looper();
9
10      sub looper {
11:         my $arg = 0;
12:         while ($arg < 10) {
13:             ++$arg;
14          }
  DB<1> a 12 print "arg is now $arg... "
  DB<2> b 12 ($arg > 8)
  DB<3> c
arg is now 0... arg is now 0... arg is now 1... arg is now 1... arg is now 2...
arg is now 2... arg is now 3... arg is now 3... arg is now 4... arg is now 4...
arg is now 5... arg is now 5... arg is now 6... arg is now 6... arg is now 7...
arg is now 7... arg is now 8... arg is now 8... main::looper(testDebugger.pl:12)
:           while ($arg < 10) {
  DB<3> ow 9...

You can see on the last line that the output generated by actions can become intermixed with that generated by the debugger itself.