Item 38: Learn to use a debugging version of Perl.


You don't actually need a debugging version of Perl to debug Perl programs. However, it's fun to have one to play with, and it's also instructive to build one so that you can see how to install more than one copy of Perl on your system. You will need a debugging version of Perl if you plan to write XS modules (see Item 47) or call Perl from another program.

Building a debugging version of Perl

If the -D command line option on your installed version of Perl doesn't work, you need to build a debugging version of Perl for your private use. If the -D option does work, you may want to ask your system administrator why Perl was installed that way, because debugging support slows Perl down somewhat.

To build a debugging version of Perl, you first need to acquire and unpack a copy of the Perl distribution that you want to install. This could be either an official "released" version or a recent development version. Both should be available through the CPAN. Configure it by running ./ Configure in the top level directory of the source. You will need to provide answers that are slightly different than usual to some of the questions:

  • Decide where you are going to install the Perl tree, then respond appropriately to the question:

     Installation prefix to use? (~name ok) [/usr/local] 

    For example, if you want the Perl tree installed in /home/joseph/perl , respond with /home/joseph/perl here.

    You should not install the debugging version of Perl in the same location as your regular copy, because the regular copy would then be overwritten. Install the debugging version in a completely separate location so that none of the debugging Perl tree overlaps the existing tree.

  • The next question to watch for is:

     What optimizer/debugger flag should be used? [-O] 

    You want to disable compiler optimization and enable debugging symbols. In most cases, this means responding to this question with the single flag -g ; however, the answer will depend on the C compiler that you are using. Do not mix -O with -g source code debuggers do not generally work well with optimized code.

  • Then you will see something like:

     Any additional cc flags? [-DDEBUGGING -I/usr/local/include] 

    Be sure to answer this question with -DDEBUGGING this option enables Perl's -D command line option. ( Configure normally suggests -DDEBUGGING if you specified the -g compiler flag.) It should appear by default if you answered the optimizer flag question with -g . You should probably also add -DDEBUGGING_MSTATS , which turns on memory usage statistics gathering if you are using Perl's built-in malloc() . If Configure suggests other flags here, leave them in.

  • If you have enabled -DDEBUGGING_MSTATS , watch for the question:

     Do you wish to attempt to use the malloc that comes with perl5? [y] 

    and be sure to answer it with y (yes). Perl's malloc() is very fast and should work on most systems. However, if it does not work on your system, you will have to go through the Configure ritual again, avoid the -DDEBUGGING_MSTATS flag, and answer n to this question.

After running Configure , you should run make and then make test . If the tests are successful (" skipped " is okay, but "failed" indicates a problem), you can then do a make install .

If you have installed a development version of Perl, you will probably want to update it with a newer development version from time to time. If you want to avoid being grilled by Configure each time you do this, just copy the previous config.sh file into the new source directory and edit it to update all of the release-specific answers. For example, if you are going from subversion 17 to subversion 19, this would mean searching for the string 17 in config.sh and replacing it with 19 wherever it is used as part of a version number. Do this manually, because numbers are used in other places in config.sh . You can then run ./Configure -d and save yourself a lot of typing.

Using a debugging version of Perl

A properly built debugging version of Perl will support both Perl's -D command line option and source code debugging via a debugger like gdb .

We won't discuss source code debugging here, although it will come in handy if you are linking other code, such as an XSUB (see Item 47), into Perl.

Perl's -D command line option is handy for peeking "under the hood" to examine the execution of a Perl program. You use it by appending a variety of debugging options to the -D option, either one or more letters like x ( syntax tree) or s (stack snapshots), or a decimal number indicating which debugging bits to set (see the man pages for the list).

Here, for example, is some output from the -Dx command line option corresponding to the statement $x += 1 :

 9       TYPE = add  ===> 10          TARG = 1          FLAGS = (SCALAR,KIDS,STACKED)         {              TYPE = null  ===> (8)                (was rv2sv)              FLAGS = (SCALAR,KIDS,REF,MOD)             {  7               TYPE = gvsv  ===> 8                  FLAGS = (SCALAR)                  GV = main::x             }          }          {  8           TYPE = const  ===> 9              FLAGS = (SCALAR)              SV = IV(1)          } 

It's verbose and somewhat obscure at first glance, but what's happening here is that Perl's internal compiler has constructed four nodes representing the operations inside the expression. These " ops" are an executable representation of Perl code.

The ops are numbered. The numbers indicate the actual execution order of the ops. The first op to be executed here is 7 ( gvsv ), which fetches a reference to the contents of $main::x and pushes it on the stack. The next one is 8 ( const ), which pushes the constant 1 on the stack. The next one is 9 ( add ), which adds the two values on the stack. The STACKED flag indicates that the result goes into the left-hand argument, that is, the second value on the stack.

The null op is a result of Perl's peephole optimizer, which combines and/or removes nodes as it traverses the initial output of the compiler.

With a different set of options, you can see a program run. Here is a sample program and some of the output generated from the -Dtls option:

 #!/usr/local/bin/perl -Dtls  $x = 10;  $x += 1;  %  tryme  EXECUTING...      =>  (tryme:0)      enter  Entering block 0, type BLOCK      =>  (tryme:0)      nextstate      =>  (tryme:5)      const(IV(10))      =>  IV(10)  (tryme:5)      gvsv(main::x)      =>  IV(10)  UNDEF  (tryme:5)      sassign      =>  IV(10)  (tryme:5)      nextstate      =>  (tryme:6)      gvsv(main::x)      =>  IV(10)  (tryme:6)      const(IV(1))      =>  IV(10)  IV(1)  (tryme:6)      add      =>  PVNV(11)  (tryme:6)      leave  Leaving block 0, type BLOCK 

The enter and leave ops indicate entry and exit of scopes at the boundaries of the program. Each Perl statement is set off by a nextstate op, which discards temporaries accumulated during the evaluation of the preceding statement and does some other bookkeeping. The other ops access variables and constants and perform arithmetic and assignments on them.

The -Dtls trace above includes running stack snapshots (the values to the right of the arrows). Notice that there are two values, 10 and 1 , on the stack before the add op, and that the sum, 11 , is placed there after the add executes. Note, also, that the result is a floating-point value (PVNV rather than IV). Using the integer module would force integer addition. Now that I brought it up, want to see integer addition at work?

Because the debugging options tend to produce large quantities of output, and because debugging logs are most useful when applied to small sections of code, generally you will find yourself turning debugging on and off dynamically by using the $^D special variable. Starting with debugging off is a good idea in the following example. Note that $^D requires an integer argument rather than a stringit's a little less user -friendly than the -D command line option:

Presuming we are starting with debugging off (no -D ) to avoid a whole pile of output at startup, then:

 use integer;  $^D = 14; 

Force integer arithmetic.

Turn on debugging (14 = bits for tls ).

 $x = 10;  $x += 1; 

See integer arithmetic at work.



Effective Perl Programming. Writing Better Programs with Perl
Effective Perl Programming: Writing Better Programs with Perl
ISBN: 0201419750
EAN: 2147483647
Year: 1996
Pages: 116

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net