The Perl Debugger

 in
Sticking in extra print statements is one way to debug your Perl code, but a full-featured debugger can give you more information.
Essential Debugger Commands

The following seven commands are sufficient for basic debugging:

  • s: single-step execute the next line, stepping into subroutines.

  • n: single-step execute the next line, stepping over subroutines.

  • r: nonstop execute until the return from the current subroutine.

  • c <line-number>: nonstop execute until a particular line.

  • l <line-number, range or subroutine>: list source code.

  • x <expression>: evaluate and pretty-print <expression>.

  • q: quit debugger.

To try these out, run the test program with the debugger:

perl -d sample.pl

You should see debugger startup information:


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::(sample.pl:6):	my $name = "Pengu";
  DB<1>

This is the state before the program starts running. The next-to-last line has useful information about the debugging status: you're in the main package, file sample.pl line 6, and it displays the line that is about to be run.

The last line is a prompt with the command number (incrementing as you enter more commands) and angle brackets, where the number of angle brackets signifies nested commands. You don't need to worry about those here.

Type s at the prompt and press Enter to single-step one line into the program:


  DB<1> s
main::(sample.pl:8):	foreach (1..20) {
  DB<1>

To repeat the command, press Enter; repeat this as long as you like to be convinced that the program is stepping through its paces. Every time you pass the print statement, it is echoed to the screen, interspaced with the debugging materials.

Now, try the command to step over subroutines (n), and press Enter a few times. You go through the loop and receive your subroutine results right away, without stepping through each command in the subroutine.

Next, try the command to return from the current subroutine (r). But wait—if you do it now, it will run until the program finishes, because you're “returning” from the main program. First, do a couple repetitions of s to step into the subroutine. Then, with an r, you should see something like:


  DB<1> s
main::(sample.pl:8):	foreach (1..20) {
  DB<1>
main::(sample.pl:9):	  &shout($name);
  DB<1>
main::shout(sample.pl:13):	  my $name = shift;
  DB<1> r
*** Pengu ***
void context return from main::shout
main::(sample.pl:8):	foreach (1..20) {
  DB<1>

Notice the void context return from main::shout line. If we had asked for a return value in the main loop, we would see it displayed here. In Perl, functions and subroutines can return different values based on the context of the caller (scalar, array or void). A nice feature of the Perl debugger is the r command, which tells you what context was requested by the caller. It can find the bug if you ask your subroutine for a scalar, but you mistakenly have the subroutine return an array.

Next, we have the l command. Try it now:


  DB<1> l
8==>    foreach (1..20) {
9:        &shout($name);
10      }
11
12      sub shout {
13:       my $name = shift;
14:       print "*** $name ***\n";
15      }
  DB<1>

Alone, l lists a page of the source code, starting at the next line to be executed, with a text arrow pointing to the next line. You also can list a range by specifying the line numbers, such as l 200-230. Additionally, you can list a subroutine by naming it: l shout.

The c command continues execution until you hit a particular line number, so you can jump ahead to a particular piece of code that is interesting:


  DB<1> c 14
main::shout(sample.pl:14):  print "*** $name ***\n";
  DB<1>

You can execute any Perl expression, including code that changes the running program, by typing it at the prompt. This can include setting variables in the program by hand.

The x command evaluates and pretty-prints any expression, prepending a numbered index on each line of output, dereferencing anything that can be dereferenced and indenting each new level of dereferencing. As an example, below we set an array, @sample, and then display it:


  DB<1> @sample = (1..5)

  DB<2> x @sample
0  1
1  2
2  3
3  4
4  5
  DB<3>

Notice that hashes are displayed with keys and values, each one on a line. You can display hashes properly by preceeding the hash with a \, which turns the hash into a hash reference, which is properly dereferenced. This looks like:


  DB<4> %sample = (1 .. 8)

  DB<5> x \%sample
0  HASH(0x83d53bc)
   1 => 2
   3 => 4
   5 => 6
   7 => 8
  DB<6>

When you are satisfied with the results, quit the debugging exercise with q.

______________________

White Paper
Linux Management with Red Hat Satellite: Measuring Business Impact and ROI

Linux has become a key foundation for supporting today's rapidly growing IT environments. Linux is being used to deploy business applications and databases, trading on its reputation as a low-cost operating environment. For many IT organizations, Linux is a mainstay for deploying Web servers and has evolved from handling basic file, print, and utility workloads to running mission-critical applications and databases, physically, virtually, and in the cloud. As Linux grows in importance in terms of value to the business, managing Linux environments to high standards of service quality — availability, security, and performance — becomes an essential requirement for business success.

Learn More

Sponsored by Red Hat

White Paper
Private PaaS for the Agile Enterprise

If you already use virtualized infrastructure, you are well on your way to leveraging the power of the cloud. Virtualization offers the promise of limitless resources, but how do you manage that scalability when your DevOps team doesn’t scale? In today’s hypercompetitive markets, fast results can make a difference between leading the pack vs. obsolescence. Organizations need more benefits from cloud computing than just raw resources. They need agility, flexibility, convenience, ROI, and control.

Stackato private Platform-as-a-Service technology from ActiveState extends your private cloud infrastructure by creating a private PaaS to provide on-demand availability, flexibility, control, and ultimately, faster time-to-market for your enterprise.

Learn More

Sponsored by ActiveState