Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?


by toadi (Chaplain)
on Aug 29, 2000 at 12:47 UTC ( #30091=perlquestion: print w/replies, xml ) Need Help??
toadi has asked for the wisdom of the Perl Monks concerning the following question:

Hi all,

I was wondering how people debug perl.
I never used the debugger... I just write debug-code and use the -w flag.
Who uses the debugger here and is there a reason I should use the perl-debugger?

My opinions may have changed,
but not the fact that I am right

Replies are listed 'Best First'.
RE: debugging
by tye (Sage) on Aug 29, 2000 at 18:12 UTC

    First, if you've never used the debugger before, getting started is so easy; just prepend "perl -Sd" to the command line of the script you wish to debug. The debugger will remind you to type "h h" for quick help and will show you the next line that is about to be executed. Type "n" (for "next") to execute that line. Type "s" (for "step") to start executing that line but stop if a subroutine is called so you can debug it. Type "c mysub" (for "continue") to run until "sub mysub" is called. Type "x" followed by any Perl expression to see what values result. Type any Perl code to have it executed.

    perl -Sd scriptname -scriptoptions scriptarguments DB<1> h h DB<2> |h
    The "-S" tells Perl to find your script where ever it is in your $ENV{PATH}. The "-d" tells Perl you want the debugger. The "h h" gives you help on the "help" command, which is a quick one-screen run-down of all of the debugger commands. "|h" pipes the output of the full "help" command through your default "more"-like program so you can read it all.

    I use the debugger frequently. Although the turn-around time between adding print statements and rerunning your script is much lower in Perl than in a more traditional compiled language, it is still much, much slower than adding the print statements interactively only where and when you want them via the debugger. Especially since you can type x $self and see complex nested data. Even if you've gone out of your way to make "print" debugging easy, you can't add as useful of a print statement to your code with fewer keystrokes.

    You can test possible fixes to your bugs right there in the debugger. "Oops, off by one," then just add or subtract one right there and see if the next result becomes correct. Say the debugger has convinced you that you have a complex bug that will take some work to correct. Just replace the incorrect result with the correct one and you can continue verifying or debugging the rest of your code in the mean time.

    If you've never used the debugger, then I'll bet you've never run into a bug that manifests itself late in a long-running script. Debugging those with print statements is very frustrating ("Oops, didn't print enough. Now I've got to wait another 20 minutes to see if I located where the bug really is this time", "Oops, shouldn't have put that print statement there. It will take me an hour to cull through all of that output and it is making the run take three times as long").

    There are three things that I notice the debugger is currently not suited for: playing with "-w", "use strict", and regular expressions. The first is just a design decision that means that "-w" is not in effect for code that you type at the debugger prompt. This is easy to patch but has not been done yet. The second is similar but would probably need to be fixed as a debugger "option".

    The last has to do with the debugger's valiant but still-insufficient attempts to save and restore the complex regex context for you. The debugger itself uses regexen to figure out what command you just entered. It tries very hard to save and then restore the state of all of the regex-related variables associated with the code you are debugging so that its own use of regexen doesn't change the behavior of your program. But it doesn't always succeed. This is especially true if you are typing regexen at the debugger prompt. If you aren't getting what you expected, then ask for your results with the same line of input that performed the regex (which will still fail for the new and highly magical @- and @+).

    I also use the debugger interactively via "perl -de 0" even more often. It is useful for making quick calculations, playing with ideas that will turn into scripts, exploring the language and modules, or just getting one-off work done. My Win32API::File and related modules are designed for easy use from the debugger. I've used them to do things like interactively compare and correct boot sectors. If you are on Win32, you should try this:

    perl -de 0 DB<1> use Win32API::File ":ALL" DB<2> |m Win32API::File [...] createFile [...] DB<3> createFile() Win32API::File::createFile() usage: $hObject= createFile( $sPath, [$svAccess_qrw_ktn_ce,[$svShare_rwd,]] [{Option=>$Value} +] ) options: Access Create Share Attributes Flags Security Model Called at (eval 7)[F:/Apps/Perl/lib/] line 2 DB<4> createFile("","?") Win32API::File::createFile: $svAccess can use the following: One or more of the following: q -- Query access (same as 0) r -- Read access (GENERIC_READ) w -- Write access (GENERIC_WRITE) At most one of the following: k -- Keep if exists t -- Truncate if exists n -- New file only (fail if file already exists) At most one of the following: c -- Create if doesn't exist e -- Existing file only (fail if doesn't exist) '' is the same as 'q k e' 'r' is the same as 'r k e' 'w' is the same as 'w t c' 'rw' is the same as 'rw k c' 'rt' or 'rn' implies 'c'. Or $svAccess can be numeric. Called from at (eval 13)[F:/Apps/Perl/lib/] line 2 DB<5>
    See, you don't even need to remember how to use the module.

            - tye (but my friends call me "Tye")
RE: debugging
by jeorgen (Pilgrim) on Aug 29, 2000 at 14:56 UTC
    Here are some tools I use:

    I've noticed that a lot of my debugging time is spent debugging the wrong code, i.e the error is somewhere else than I think. This is because you narrow down to quickly on a perceived problem, and because errors get layered on top of each other, so that the cause of the error is actually some minutes, or even days old. One remedy to this is to use

    perl -c
    every minute or so, so that you catch little syntax errors when they are done. If you're in an error-prone mode otherwise little errors will be layered on top of each other.

    A graphical debugger like ptkdb is really good for those (like me:-) who have problem keeping structures in (the brain's) memory. Graphical debugger means see-and-act instead of remember-and-type.

    While programming, write little test scripts to test how certain things in perl work, before you rely on them in your scripts. Save the test scripts with a comment on what happened.

    Use print statements to check what is actually happening in your script. Use Data::Dumper (in the core distribution) to print out complex structures. Here is a module I use. It is a hack but it seems to do what I want:

    package jmdebug; # Debugging module # # # PURPOSE: to provide debugging information concerning methods # # CALLING FORMAT: # jmdebug::output("Description text",$scalarvariable_or_complex_refere +nce); # Put the above line with modification in e.g. any metod calls you wan +t to keep tabs on # In order to include several variables, do something like this: # jmdebug::output("Description text",\[$var1,$var2,\@array1]); # # BEHAVIOUR:checks to see if global var $debug is true, tries to gathe +r information in a subroutine context # which is done with the caller(1) syntax. If that does not work does +a plain caller(0) function call # Tries to pretty-print results use Data::Dumper; # used to display data structures sub output { if ($main::debug){ my ($pack, $filename, $line, $sub, $arg, $context, $dummy, $subnam +e); ($pack, $filename, $line, $sub, $arg, $context) = caller(1) or ($ +pack, $filename, $line, $dummy, $arg, $context) = caller(0); $text = shift @_; my $datastructure = shift @_; $datastructure = Dumper($datastructure); $datastructure =~ s§^\$VAR1 \= §§; $subname = $sub; $subname =~ s§^.*\:\:§§; my ($pre, $post); if ($main::debug_html) { $pre = "<PRE>"; $post = "</PRE>"; } print (qq§ $pre _____ / \\_________________________________________________ | | $subname : | ** $text ** | package: $pack | line: $line | in subroutine: $sub variable contains: $datastructure | |__________________________________________________________ $post§);} } 1;

    Finally, write test scripts to give your subs or methods a run-through with different parameters and scenarios.


RE: debugging
by t0mas (Priest) on Aug 29, 2000 at 13:13 UTC
    I use the debugger while practicing the noble art of debugging :) The main reason I use it, is to inspect variables during execusion of complex scripts. Sometimes my scripts produce other output than exepcted...

    Here and here are two links to articles that you might find useful.

    /brother t0mas
RE: debugging
by Jouke (Curate) on Aug 29, 2000 at 16:19 UTC
    I never used the 'normal' debugger, but I can't live without ptkdb (see CPAN), the Perl TK Debugger. For small scripts I use the method merlyn uses (just "print" variables and things, incrementally developing the script), but for complex applications with a lot of code written by more than 1 person, databases and lots of classes/modules, I cannot develop without ptkdb anymore.

    I used ActiveState's Debugger at first, which is almost as good (except for the variable watching), but since I don't want to use windows anymore, I started using ptkdb, which does a better job!

    Jouke Visser, Perl 'Adept'
RE: debugging
by merlyn (Sage) on Aug 29, 2000 at 15:13 UTC
    I don't use the debugger to "debug" my code either: I come from the old school, where you just add print until it works. {grin} And since that's pretty painful, I usually just do incremental development, adding one little piece at a time, and running the code each time, so that I can tell where it broke when I broke something.

    I do use the debugger frequently as an interactive Perl:

    $ perl -deal
    because the ability to type x arbitrary expression is pretty cool for testing out snippets.

    -- Randal L. Schwartz, Perl hacker

      The line:
      print DEBUGOUT "\$var=$var\n" if DEBUGGING
      Shows up all over my scripts. If I declare DEBUGGING as a constant the branches get compiled out, and I can choose to log the debug data for later or direct it to STDERR or STDOUT. I havn't done it yet, but I've been thinking about using btrott's Filehandle Filter to do even more with the DEBUGOUT filehandle. Oh, and is very useful too. Its rare that this technique doesn't provide me enough info and I have to resort to the debugger. But its nice to know that the debugger is there when I need it.
      Actually I agree zith Merlyn. I don't have the ability to over see big problems. I just program a little, try it and add some more. I put print a lot... I just wanted to know if this was a good method.

      My opinions may have changed,
      but not the fact that I am right

RE (tilly) 1: debugging
by tilly (Archbishop) on Aug 29, 2000 at 15:48 UTC
    Like others here I only use the debugger for interactive use.

    Instead I rely on having lots of internal checks to catch mistakes early. Things like always checking return codes of system calls, validating input to programs, writing stubs, having a verbose mode I can turn on. Actually reading my code periodically.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://30091]
Approved by grinder
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others chanting in the Monastery: (5)
As of 2018-01-17 19:07 GMT
Find Nodes?
    Voting Booth?
    How did you see in the new year?

    Results (203 votes). Check out past polls.