August 09, 2001
Using the Perl Debugger
brian d foy
In this article, I show you how to use the Perl debugger to execute arbitrary Perl statements, create and examine variables, and step through and set breakpoints in programs so that you can start using the Perl debugger right away. As you get comfortable with the basics, you can start to explore its other features.
Using the Perl Debugger
Perl comes with a built-in debugger. Although you could use third-party debuggers
such as perltkdb and ActiveState's Komodo, which provide a graphical interface,
you already have everything you need if you have Perl. In this article, I show
you how to use the Perl debugger to execute arbitrary Perl statements, create
and examine variables, and step through and set breakpoints in programs so that
you can start using the Perl debugger right away. As you get comfortable with
the basics, you can start to explore its other features.
The Perl debugger is started by specifying the -d switch on the command
line. The simplest way to run the debugger is with a command-line script using
the -e option to perl.
The script can be anything that is valid Perl. In this case, I use the single
statement 0 since it is easy to type and will not get in my way
as I explore the debugger. This example script is only half as long as the one
used in the perldebug man page.
The debugger starts up and displays some initial information about
itself, including its name (perl5db.pl), its version (1.07),
and how you can get more information about the debugger.
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::(-e:1): 0
DB<1>
|
The debugger starts at the first executable statement in the script, in this
case
0, then waits for my instructions. It has not executed anything
yet. I can tell where the debugger is because it displays quite a bit of information
in its prompt. The prompt tells me that the current namespace is
main::,
the name of the script is
-e (since I invoked
it from the command line), and that the debugger is at line 1, which has the
statement
0. The debugger is waiting for a command at the
DB<1>
prompt, which tells me that I am at the first debugger instruction.
I do not especially care about this simple script since I really want to test
some Perl statements without creating a script to go around them. The debugger
allows you to enter arbitrary statements. Anything that does not look like an
instruction to the debugger is
evaled as Perl code.
main::(-e:1): 0
DB<1> @order = ( 1, 'cherry', 3.14 )
DB<2>
|
I created an array,
@order, and assigned it a list of values. The debugger
accepted that statement,
evaled it, and prompted me for another instruction.
If I enter something that is not a valid Perl statement, the debugger complains
and then continues.
DB<2> $y =
syntax error at (eval 24)[/System/Library/Perl/perl5db.pl:1513] line 2, at EOF
DB<3>
|
Now that I have created
@order, I want to examine it to check its contents.
The debugger has several commands to let me see what is happening in my program.
The
x command allows me to examine the variable that I specify.
DB<3> x @order
0 1
1 'cherry'
2 3.14
DB<4>
|
The debugger pretty prints the array in two columns. The first
column is the element index, and the second column is the
corresponding value. If I had done this with a hash, the
debugger still pretty prints it as a list, but in key-value
pairs. Since a hash is unordered, the indices in the first
column do not mean much to me.
DB<4> %hash = ( one => 1, two => 2, three => 3 )
DB<5> x %hash
0 'one'
1 1
2 'three'
3 3
4 'two'
5 2
DB<6>
|
Even when I create and examine a scalar I see the two column
display of the variable when I examine it, although a scalar
only ever has one value.
DB<6> $pi = 'apple'
DB<7> x $pi
0 'apple'
DB<8>
|
I can even examine more than one variable at a time, even though the debugger
makes me remember in which order I specified them.
DB<8> $n = 3; $m = 4; $o = 6
DB<9> x $n, $m, $o
0 3
1 4
2 6
DB<10>
|
I can also use the
p command, which does the same thing as the
perl
builtin
print() function, to print the values in these variables, rather
than dumping the variables as the
x command does.
By this time, I think I have forgotten which variables I have defined, but
I can use the
V command to pretty print all of the variables in a package,
defaulting to
main::. Try this yourself you may be surprised how
many variables are actually defined in
main::. I can also limit the variables
that
V dumps by specifying the package and variables I want to see.
DB<10> V main pi
$pi = 'apple'
DB<11>
|
Notice that I do not need to specify the variable symbol, such as
$,
@, or
% in front of the variable name. The
V
command shows me all values for any variable with that name, including variables
without special symbols.
DB<11> @pi = qw(peach cherry)
DB<12> V main pi
$pi = 'apple'
@pi = (
0 'peach'
1 'cherry'
)
DB<13>
|
Try opening a file onto a filehandle named
pi and see what
V
reports.
To make things a bit simpler, I created another variable in a different package
by specifying the fully qualified name in the declaration. When I use the
V
command for that package, I only see the variables in that package.
DB<13> $my_main::foo = 42
DB<14> V my_main
$foo = 42
|
The X command does the same thing as the
V command, although it defaults
to the current package rather than
main::.
For extra credit, create a lexical variable using
my() and try the
V command again. Where is the lexical variable?
*
Now the I have shown you some of the basics for using the Perl debugger, let's
invoke it on a real (toy) script, which I call test.pl.
1: #!/usr/bin/perl
2:
3: $x = 5;
4:
5: $y = 42;
6:
7: $z = $x + $y;
8:
9: print "z is $z\n";
10:
11: print "z^2 is " . $z * $z . "\n";
12:
13: __END__
|
I invoke the debugger as before.
Again, the debugger stops right before the first executable statement and
tells me the current package, the name of the script, the current line number,
and current statement. The first thing that I probably want to do is to execute
this statement, unless I think there are bugs in the program before I even start
running it. I can single step through the program with the
s command.
The debugger only executes the next statement and then prompts me for additional
instructions. I can also examine variables with the
x command, or use
any other debugger commands.
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::(test.pl:3): $x = 5;
DB<1> x $x
0 undef
DB<2> s
main::(test.pl:5): $y = 42;
DB<2> x $x
0 5
DB<3> s
main::(test.pl:7): $z = $x + $y;
DB<3> x $x, $y
0 5
1 42
|
If the next statement includes a subroutine call and I single-step through
that statement with the
s command, the debugger descends into the subroutine
and I can single-step through each subroutine statement. I can skip this descent
by using the
n command, which executes the subroutine completely and
returns control to me at the next program statement after the subroutine call.
Simply typing a carriage return at the debugger prompt will repeat the last
s or
n command.
DB<4>
main::(test.pl:9): print "z is $z\n";
DB<4>
|
While I step through the program, I can examine the lines that are next or
the lines that I just executed. The
w command shows a window of lines
around the current line and precedes them with their line numbers. It shows
lines that are executable statements with a
: after the line number,
and shows the current line with a
==>.
DB<4> w
6
7: $z = $x + $y;
8
9==> print "z is $z\n";
10
11: print "z^2 is " . $z * $z . "\n";
12
13 __END__
|
If I want to examine a different window of lines, I can specify those lines
with the
l command. This command has many ways to specify which lines
to show, but I am just going to specify a range of lines.
DB<4> l 3-7
3: $x = 5;
4
5: $y = 42;
6
7: $z = $x + $y;
|
Once I am satisfied that at least some of the statements are executing correctly
and as I expect them to, I want to let them execute automatically and stop at
the parts of the program that I need to examine more closely. I can set breakpoints
at certain lines so that the debugger stops and I can issue debugger commands.
There are several ways to set breakpoints, including by line number and by line
number if some condition is met (such as a variable having a certain value).
All of them are explained in the
perldebug man page.
Here I am only going to set a breakpoint by line number so I can stop right
before the print statement.
When I invoke the debugger, the same thing as before happens. Instead of single-stepping,
I use the
b command to set a breakpoint at line 9.
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::(test.pl:3): $x = 5;
DB<1> b 9
DB<2>
|
Now that I have set a breakpoint, I use the
l command to look at the
lines around the breakpoint. Notice that line 9, which has the breakpoint, has
a special notation next to its line number to indicate the breakpoint.
DB<2> l 6-12
6
7: $z = $x + $y;
8
9:b print "z is $z\n";
10
11: print "z^2 is " . $z * $z . "\n";
12
DB<3>
|
To run the program up to the breakpoint without stopping for each statement,
I use the
c command. The program runs up to line 9, then
pauses to prompt me for further commands. At this point, I can do any of the
things that we have seen so far, including executing arbitrary Perl statements
that can influence the state of the program. I can examine and change variable
values if I choose.
DB<3> c
main::(test.pl:9): print "z is $z\n";
DB<3> x $z
0 47
DB<4> $z = 5
DB<5> x $z
0 5
DB<6>
|
If I no longer need a breakpoint, I can delete it with the
d command.
When I look at the window again, I no longer see the breakpoint annotation next
to line 9. If I want to clear all breakpoints, I use the
D command.
DB<6> d 9
DB<7> w
6
7: $z = $x + $y;
8
9==> print "z is $z\n";
10
11: print "z^2 is " . $z * $z . "\n";
12
13 __END__
DB<7>
|
Besides the commands I have shown in this article, you can do many other things
with the debugger, including setting actions for a particular line, changing
the behavior of the debugger by setting or changing options, and examining the
debugger itself. Now that you know enough to start using the debugger right
away, you can explore these other features on your own and start finding those
bugs in your own programs.
Happy bug squashing. :)
[*] Obviously the V command dumps everything
it finds in the symbol table. These are package variables, which is why you
can specify a package with this command. Since lexical variables carry no package
information and are not stored in the symbol table, the V command does not know
they exist.
brian d foy has been a Perl user since
1994. He is founder of the first Perl users group,
href="http://ny.pm.org/">NY.pm
, and Perl Mongers,
the Perl advocacy organization. He has been teaching Perl through Stonehenge
Consulting
for the past three years, and has been a featured speaker at
The Perl Conference, Perl University, YAPC, COMDEX, and Builder.com. Some of
brian's other articles have appeared in The Perl Journal.