A short introduction to the perl debugger's basic commands for executing code, examining data structures. Includes examples of hardwiring breakpoints, tracing sections of code, debugging regexen.
How to Troubleshoot Apps for the Modern Connected Worker
Short Introduction To "perl -d"
1. Basics of perl -d
Steven Lembark
Workhorse Computing
lembark@wrkhors.com
2. Introducing Perl's Debugger
● Overview of the obvious uses, common commands.
● Few less obvious uses:
● Debugging regexen.
● Evaluating structure bloat.
● Some pitfalls and how to avoid them.
3. What is the Perl Debugger?
● The Perl debugger comes with perl, in fact it is perl.
● 'd' is built into perl's command line.
● It functions like a perly shell, evaluating source code
from files or the command line or executing
debugger commands.
● You also use perl d with profiling utilities like
NYTprof.
4. Smarter Than Your Average Code
● The most obvious thing you can do is walking code
to track down bugs.
● You can also test Perl syntax: just type it in.
● Use it as a “perly shell” when your oneliners run
into multiple lines or you have to eyeball data
structures between commands.
● Q&D interactive data mining.
● Good for examining data structures when writing
talks on data manglement or module guts.
5. The Basics: Getting In
● At the command $ perl d e 42;
line: perl d enters $ perl d foo.pm;
the debugger.
$ perl d bar;
● You can start it
'vanilla', with $ perl MDevel::Size d e foo;
modules to watch
startup, with code,
or using modules to
pull in utilities (e.g.
regex debugging).
6. Basics: The Prompt
● Once in you get the command prompt:
$ perl d e 42
Loading DB routines from perl5db.pl version 1.22
Editor support available.
Enter h or `h h' for help, or `man perldebug' for more help.
main::(e:1): 42
DB<1>
● This is a “vanilla” session: there is no running code,
you can enter debugger commands, perl syntax.
● The single “<1>” indicate that this is the outermost
call level.
● The “1” says that this is the first command.
7. Executing Perl Statements
● Q: Who remembers what localtime returns?
● A: How to find out?
DB<1> x
localtime
0 31
1 31
2 15
3 15
4 5
5 111
6 3
7 165
8 1
DB<2>
● Notice that now I'm at command #2.
8. Gotchas
● Each command you type is run its own block.
● Lexical variables like “my $foo” will vanish.
● Local values like “local $” or “local $foo{ bar } = ...”
will also be unavailable after the line completes.
● You can put multiple statements onto a line with
semicolon separators.
● You can only input one line at a time.
● Cutandpaste of multiple lines won't work.
9. Debugger Commands
● These intentionally look pretty much like gdb.
● On the other hand, if you didn't grow up debugging C
code this may not help you much.
● The most common commands are for running code,
managing breakpoints (i.e. stopping code),
interrogating values.
● Please note: “q” gets you out.
● Not “quit”, ^C, ^D, or “getmeoutofhere!”.
10. Setting Up the Debugger
● You may want to edit your commands.
● Installing Term::ReadKey &Term::ReadLine.
● perl will use your .inputrc if you have one.
● For example, my .inputrc looks like:
set editing-mode vi
set show-all-if-ambiguous on
with allows ^[k to pull up the last line for editing.
● Check the doc's if you use Emacs.
11. Running Code
● Say some code blows up.
● You could just run it with “r” from the start.
● That is handy once to see where it blows up.
● Usually you want to stop at a particular place to see
why it blows up.
● You can continue to a line no or sub name with:
c 15
c call_foomatic
12. Stepping Code
● You can also watch the code one line at a time.
● “n” (“next”) steps over the subroutine calls.
● “s” (“step”) steps into the subroutine calls.
● “r” (“return”) goes back to the caller if you accidentally
step one level too deep.
● One really common combination:
● “c” to a subroutine that blows up.
● “n” to the point before it dies.
● “s” into the call that failed and see what happens.
13. Getting Out of a Hole: “r”
● Sometimes you 's' into the wrong sub (say a DBI
call).
● You don't want to abort the session.
● You don't want to “n” your way through DBI.
● Use “r” to return from the current call.
● This also shows you the return value passed back to
the caller.
● Nice for checking that what you expect gets returned.
● Beware if the structure is really large.
14. Stopping Code: Breakpoints
● Breakpoints stop the code.
● They can include a condition.
● Say the code blows up at line 842 with a non
reference value in $thingy after roughly 8_000
iterations.
● Set a breakpoint and continue:
<1> b 842 ! ref $thingy
<2> c
16. Hashes Are Lists to “x”
● Hashes look a little odd at first:
DB<8> x %a = map { $_ => [ 1 ] } ( 'a' .. 'c' )
0 'a'
1 ARRAY(0xc122a0)
0 1
2 'b'
3 ARRAY(0xb07fe0)
0 1
4 'c'
5 ARRAY(0xc122e8)
0 1
● They look exactly like the array: a list.
17. Hashref's Are Structures
● Examining a hashref shows it as key => value pairs:
DB<9> x %a
0 HASH(0xc47008)
'a' => ARRAY(0xc122a0)
0 1
'b' => ARRAY(0xb07fe0)
0 1
'c' => ARRAY(0xc122e8)
0 1
18. You Don't Always Want It All
● Occasionally you'll get something like:
0 ARRAY(0xc99050)
0 ARRAY(0xc99080)
0 ARRAY(0xc990b0)
0 ARRAY(0xc990e0)
0 ARRAY(0xc99110)
0 ARRAY(0xc99140)
empty array
DB<17>
● This was a structure that didn't fit onto the screen.
● Use “x” with a limit to display less of it.
19. Getting What You Need
● A digit following “x” limits the depth:
DB<26> $i = 'z'
DB<27> $a = $b = []
DB<28> for( 1 .. 100 ) { $b = $b->[0] = [], $b->[1] = ++$i }
DB<29> x 6 $a
0 ARRAY(0xc90e38)
0 ARRAY(0xc917f8)
0 ARRAY(0xc988e8)
0 ARRAY(0xc98af8)
0 ARRAY(0xc98a20)
0 ARRAY(0xc98b10)
1 'ad'
1 'ac'
1 'ab'
1 'aa'
20. Mining Large Data Structures
● x 2 $struct will show the top level, including hash
keys or offset lists.
● x 2 $struct>{ key } will show the single hash value.
● To walk through a structure in viewable chunks:
● x 2 $struct>{ key1 }{ key2 }
● See what matters, paste on the next key/offset and keep
looking:
● x 2 $struct>{ key1 }{ key2 }[ offset ]
21. You Are Here
● The “T” command provides a stack trace.
● Useful with hardwired breakpoints.
● They show the calling line numbers and values.
● Makes it easier to set breakpoints up the stack to see how
values are [mis]managed down the call stack.
● Viewing the code uses “l” and “v”.
● “l” (list) shows the next line to be executed.
● “v” (view) shows a small window around the line.
22. Finding Out What You Can Do
35: my $frag
36: = WCurve::Fragment->new
37: (
● “m” shows the 38:
39: );
FloatCyl => ( $base x $length ), $name
methods of an DB<1> n
Testify::(01-FloatCart-basic-geometry.t:41):
41: ok $frag eq $name, "Name: $frag ($name)";
object. DB<1> m $frag
add_skip_chain
carp
● Items with confess
converge_limit
looks_like_number
package via WCurve::Fragment: (""
prefixes are via
via
WCurve::Fragment:
WCurve::Fragment:
()
(0+
via WCurve::Fragment: (bool
inherited. via
via
WCurve::Fragment:
WCurve::Fragment:
(int
stop_offset
● Leading '(' is via
via
WCurve::Fragment: sum
WCurve::Fragment -> ArrayObj: (<=>
an overload. via
via
WCurve::Fragment -> ArrayObj: (cmp
WCurve::Fragment -> ArrayObj: DESTROY
via UNIVERSAL: DOES
via UNIVERSAL: VERSION
via UNIVERSAL: can
via UNIVERSAL: isa
23. Hardwired Breakpoints
● Because the perl debugger is written in perl, you can
also set “hardwired” breakpoints:
$DB::single = 1;
$DB::single = 1 unless ref $thingy;
$DB::single = 1 if $counter > @itemz;
● These can be useful in permanent code:
eval { … }
or do
{ print $@; $DB::single = 1; 0 };
24. Tracing Code
● Tracing code usually produces too much output.
● To turn on tracing use $DB::trace = 1.
● You can localize it to trace a code block.
● Add iflogic to trace code leading up to errors:
$DB::trace = 1 if ! ref $foo;
● One trick for restartable subs is to eval them and
trace the failures:
eval { foo } or do{ trace = 1; foo }
25. Ever Wonder How a Regex Works?
● The “re” module allows debugging regexen:
use re 'debug';
use re 'debugcolor';
● There is more info in “perldoc perldebug”.
● A monochrome example:
26. DB<7> do { use re 'debug'; $a = qr/ (w+) $/x; print 'this is a test' =~ /
$a/; }
Compiling REx " (w+) $"
Final program:
1: OPEN1 (3)
3: PLUS (5)
4: ALNUM (0)
5: CLOSE1 (7)
7: EOL (8)
8: END (0)
floating ""$ at 1..2147483647 (checking floating) stclass ALNUM plus minlen 1
Guessing start of match in sv for REx " (w+) $" against "this is a test"
Found floating substr ""$ at offset 14...
start_shift: 1 check_at: 14 s: 0 endpos: 14
Does not contradict STCLASS...
Guessed: match at offset 0
Matching REx " (w+) $" against "this is a test"
Matching stclass ALNUM against "this is a test" (14 chars)
0 <this is a >| 1:OPEN1(3)
0 <this is a >| 3:PLUS(5)
ALNUM can match 4 times out of 2147483647...
4 <this is a test>| 5: CLOSE1(7)
4 <this is a test>| 7: EOL(8)
failed...
...
1 <this is a t>| 5: CLOSE1(7)
1 <this is a t>| 7: EOL(8)
...
7 <this is a test>| 5: CLOSE1(7)
7 <this is a test>| 7: EOL(8)
failed...
...
10 <this is a test>| 3:PLUS(5)
ALNUM can match 4 times out of 2147483647...
14 <this is a test>| 5: CLOSE1(7)
14 <this is a test>| 7: EOL(8)
14 <this is a test>| 8: END(0)
Match successful!
test
DB<8>
27. Benchmarking Size
● Devel::Peek && Devel::Size show the contents and
size of structures inside of perl.
● There are lots of examples in Perl Memory
Manglement, which is mostly a session of
perl -Mdevel::Size -d -e 0;
● The advantage to dealing with this in the debugger is
being able to interactively query the sizes of sub
structures to see where bloat comes from.
28. Knowing When You're There
● The variable $^P will be true when code is running
in the debugger.
● This allows you to automatically set hardwired
breakpoints or verbosity:
my $max_verbose = $cmdline{ verbose } > 1 || $^P;
29. Spoon Feeding
● The debugger does not handle forks automatically.
● The problem is that multiple processes latch on to the tty
device files for input and output.
● You can set the display to a set of perinitialized ttys
(usually preopened xterm's).
● At that point you can switch to the alternate terminals to
handle each session.
30. Semiautomated Forks
● You can usually dodge the issue by simply not
forking in the debugger:
if( my $pid = $^P ? '' : fork )
{
# parent
}
elsif( defined $pid )
{
# child, debugger
}
else
{
die "Phorkafobia: $!";
}
31. A Modern Version
given( $^P ? '' : fork )
{
when( '' ) { ... }
when( undef ) { die "Phorkafobia: $!" }
my $child = wait;
# parent processes results.
}
32. Further Reference
● A always, perldoc is your friend.
● perldoc perldebug
● perldoc perlre
● Perldoc DB
● For examples of querying memory use:
● perldoc Devel::Peek
● perldoc Devel::Size
● http://www.slideshare.net/lembark/perl5memorymanglement