Melly has asked for the wisdom of the Perl Monks concerning the following question:

I'm not sure if this is a Meditation or a SoPW, but it's certainly a confession of sorts.... (monks, confession, oh never mind...)

I have never knowingly run a perl program with the -d switch (correction, I've run programs with the -d switch - but more out of curiosity rather than with useful intent).

I suspect that this might be a fairly common confession - particularly for self-taught coders and/or those without a background in C, C++, whatever...

Instead, my code tends to look like:

my $debug = 1; .... print "Current record is: $recno and used flag is $used\n" if $debug;

So... is this the sort of thing that I should be using the perl debugger for? And, if so, how? And are there times where "$debug" is a better approach?

AFAIK this site doesn't have much in the way of a debugger tutorial, so give me some good answers and I'll try and compile the best advice into one.

map{$a=1-$_/10;map{$d=$a;$e=$b=$_/20-2;map{($d,$e)=(2*$d*$e+$a,$e**2 -$d**2+$b);$c=$d**2+$e**2>4?$d=8:_}1..50;print$c}0..59;print$/}0..20
Tom Melly,

Replies are listed 'Best First'.
Re: Using the Perl Debugger (-d)
by gaal (Parson) on Jan 25, 2007 at 13:35 UTC
    Debug prints such as yours entail a runtime hit, which is almost always negligible; but they also clutter the code, which often isn't.

    I'm not saying never put in debug prints and prefer the debugger instead--I prefer prints myself--but it's useful to distinguish prints you put in for fixing a particular problem at hand, which are usually temporary and removed after the problem is resolved, and logging messages, which are usually permanent even if easily turned off.

    For the latter, there are many elaborate logging packages on CPAN, such as Log::Dispatch and Log::Log4perl to name two. For the former, where both informativeness and easy removal are important I usually use these subs which I stick in some common module:

    sub ::Y { require YAML::Syck; YAML::Syck::Dump(@_) } sub ::YY { require Carp; Carp::confess(::Y(@_)) }
    (It used to be ::D and ::DD using Data::Dumper instead of YAML::Syck, but I often end up installing the non-core Y::S on systems I use anyway, and I like its output better.)
      Debug prints such as yours entail a runtime hit, which is almost always negligible; but they also clutter the code, which often isn't.
      If you use something like this:
      use constant DEBUG => 1; print "Some useful information" if (DEBUG);
      the compiler should optimize it away, which will remove even the small performance hit (or at least relegate it to the one-time compilation of the code).
        I have used your same approach sometimes. The problem I hit is that if your program has been migrated to a production environment where the script is read-only, you cannot turn on/off the switch for debugging purposes.
        That is why I prefer to add a command-line switch to turn on debugging:
        #!/usr/bin/perl -s use warings use strict;
        use vars $d;
        use vars qw/$d/; print "Debugging message..." if $d;
        To run the script you would use perl -d

      Smart::Comments don't really clutter the code...

      cheers --stephan
        You posted that when I was over to CPAN to get the link. :-)

        I love Smart::Comments! Basically, it requires you to write debug comments like this:

        sub foo { ### entering foo my $x = shift; ### x: $x return $x + 1; } ### starting... my $y = foo(42); ### y: $y ### finish exit;

        As you can see, they're just simple comments, until you use Smart::Comments, when they'll magically print the following output to STDERR:

        ### starting... ### entering foo ### x: 42 ### y: 43 ### finish

        The best part is that, when you disable Smart::Comments, they will sit quietly there -- just like comments they are -- documenting your code, but not being executed.

        Simple, useful... smart!!! :)

Re: Using the Perl Debugger (-d)
by liverpole (Monsignor) on Jan 25, 2007 at 13:46 UTC
    The same goes for me.  The Perl debugger is one of those tools that I keep meaning to learn more about.

    However, in my case I think it's because I have a background in C.  I've used several debuggers for compiled C code, but I always come back to using one of 2 things:  printf( ... ), and some mechanism of saving data to a logfile.

    Part of my rationale in debugging that way in "C" is that it's best to take a "minimally invasive" approach when it comes to debugging.  If you have to recompile your program to support debugging, there's often a chance that you've changed the behavior of the bug; possibly even eradicated it.

    One of the things I do at work is maintain the local Bugzilla code.  Whenever a tricky bug is found (as one was just this morning), the first thing I do is replicate the code and the mysql database to a test version on the same server (using a Perl script, of course ;-)), and then use some Perl subroutines to either print the data to the webpage, or save it to a logfile.  Once I've found and fixed the bug, I can migrate it back to the real version of the server fairly quickly.

    So as I say, I'll learn about the debugger one of these days, I'm sure.  But when it comes to getting real work done, sometimes the old ways are the best.

Re: Using the Perl Debugger (-d)
by osunderdog (Deacon) on Jan 25, 2007 at 13:51 UTC

    I would distinguish debugging from logging. Another peaceful monk has clarified logging. (gaal)

    I find debugging extremely useful for understanding perl behavior. Here is a link to another thread on this subject that I started a while back: Neat Debugger tricks

    Hazah! I'm Employed!


          I would distinguish debugging from logging.

      That's not strictly true.  I often encounter problems that are best debugged by doing logging.

      One example is if I'm tracking data during CGI script processing.  It wouldn't be appropriate to display the results to the generated HTML page, but adding a simple mechanism to log the results, behind-the-scenes, can be a lifesaver.

      So "logging" in the sense that I'm using it is merely another way of saying "writing data to a logfile".

      Update:  osunderdog, your good points (below) are well-taken.  I was mainly clarifying my slightly different usage of the word "logging".  Simply put, logging data to a file can be an aid to debugging.  But I see your distinction between the interaction you get with a debugger vs. the "post-mortem" aspect of perusing a logfile, after the fact.


        Ok, let me see if I can explain myself without digging a hole.

        Sure! debugging and logging are the Yin and Yang of software diagnosis.

        I guess I was distinguishing the two using interactivity as criteria. In terms of interactivity, I would consider debugging and logging as separate. Debugging allows a developer to interrogate and modify variables during runtime. Logging, on the other hand, is the passive collection of what has happened during runtime.

        I once had a Tool Vendor argue with me that logging was inappropriate for software development. His argument was that it was never introduced as a topic of discussion in college.

        Hazah! I'm Employed!

Re: Using the Perl Debugger (-d)
by orderthruchaos (Scribe) on Jan 25, 2007 at 14:03 UTC
    You might want to pick up a copy of the Perl Debugger Pocket Reference by Richard Foley. It's small, a quick read, a great reference, and has some decent examples of debugger sessions.

    Frankly, I've learned a great deal on the debugger from this book, and it's now one of my most used tools of the trade.
Re: Using the Perl Debugger (-d)
by rinceWind (Monsignor) on Jan 25, 2007 at 15:03 UTC

    There was a poll once: I usually debug via..., which would seem to suggest that you are in good company.

    I have found myself reaching for the debugger when trying to identify and fix problems in somebody else's code. Under these circumstances, I am reluctant to drop extra print or warn statements into the code, just to find out what is going on. The code could be a CPAN module I'm trying to use, or an example script.

    Since learning the basics of perl5db (perl -d), I have been using it on my own code, sometimes to quickly rectify some caffeine deficient blonde moments. I also use it to debug old code of my own that I've forgotten the fine details of.

    If perl5db is too scary, there's also Devel::ptkdb which has a much lower entry bar, especially for those not brought up on the command line.


    Oh Lord, wonít you burn me a Knoppix CD ?
    My friends all rate Windows, I must disagree.
    Your powers of persuasion will set them all free,
    So oh Lord, wonít you burn me a Knoppix CD ?
    (Missquoting Janis Joplin)

Re: Using the Perl Debugger (-d)
by Moron (Curate) on Jan 25, 2007 at 18:09 UTC
    I came from a C/Fortran/Pascal background too. During the first week I was learning Perl, (in 1999) a colleague told me to use perl -d for debugging and to then type h for a list of commands. So I learnt to use the debugger before I even knew what a hash was. I just can't imagine life without it. The "burning" features I use the most are:

    - setting breakpoints to be able to go to the (sometimes complex) problem line and sit there examining all the pieces of the expression until I find the culprit.

    - setting watchpoints so that when you don't know where the problem line is where you would be putting a printf, you can get the debugger to stop just before it is about to modify something, wherever that might be and print out the before and after values, giving you control back to look further.

    - assigning values at different points to force the path of execution to get to where you need it rather than waiting for the program to follow its "natural" course, which could be hours or days in extreme cases.

    - using CPAN and core modules, it is not always practical to put in print statements - the debugger is a lot easier than having to make modifications to code, it might also be dangerous to change published code you don't understand - and it can often be rather geeky!!

    Update: I once had to work in an environment where no predecessor had ever used the debugger. Their heavy-handed but functionally useful logging routines made it impossible to use the debugger. This meant they had to spend a lot of time in the early life of the system resetting the situation at both ends of the system and re-running with logging calls, where the debugger could have reduced it to a single run.


    Free your mind

      Nice - this gives me some concepts to play with. If nothing else, I've learnt today (from reading the excerpt from the O'Reilly book that someone posted) that perl -de 0 is a much better environment for checking quick answers to questions posted or CB'd to perlmonks...

      map{$a=1-$_/10;map{$d=$a;$e=$b=$_/20-2;map{($d,$e)=(2*$d*$e+$a,$e**2 -$d**2+$b);$c=$d**2+$e**2>4?$d=8:_}1..50;print$c}0..59;print$/}0..20
      Tom Melly,
Re: Using the Perl Debugger (-d)
by EvanK (Chaplain) on Jan 25, 2007 at 15:12 UTC
    For just validating that everything is working the way it's supposed to, I normally prefer the use of printf and Data::Dumper (and CGI::Carp for web-based apps).

    Once I've identified that there is a problem (though not necessarily what the problem is), that's when I use the debugger. If you're not dealing with a specific issue, or indeed aren't aware of any issues, then trodding through the debugger can be arduous, especially if you use a lot of subroutines.

    And, of course, debugging someone else's code...There's nothing wrong with having subroutines 10 deep in the call stack, until you try to step through them all :o

    The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.
    - Terry Pratchett

Re: Using the Perl Debugger (-d)
by Popcorn Dave (Abbot) on Jan 25, 2007 at 17:48 UTC
    Coming from a Pascal background initially, Borland Turbo Pascal 1.0 - which shows my age, I always used to rely on print statements, because at that time there wasn't a debugger. That habit carried on in to my Perl programming until I discovered -ptkdb.

    That said, it really depends on the complexity of the problem for me. I always start with the print statements if it's something that just doesn't seem right, but if it's more involved I always reack for ptkdb. I've never tried your approach since the ptkdb allowed me to add and delete variables at my leisure to watch them change.

    Now if they just had one that would help monitor Tk apps...

    Revolution. Today, 3 O'Clock. Meet behind the monkey bars.

    If quizzes are quizzical, what are tests?

      Now if they just had one that would help monitor Tk apps...

      Debugging Tk is a different ball game. Using ptkdb doesn't play well as it introduces widgets and Tk events of its own, which potentially interact with and interfere with the application you are trying to debug.

      It is possible to use perl5db on a Tk application, but using a debugger on any event driven system, like Tk or POE will always be tricky, because if your debugger is prompting you, the code cannot be servicing events. You will see your GUI freeze until you resume the application, though you can manually get GUI changes by calling $mainwindow->update from the debugger prompt.

      The approach I tend to use is to rely primarily on logging, capturing stdout and stderr in my command window's scrollback. A technique I have used is to add a debug menu under "File" on the main window's menu bar. Here's an excerpt from one of my Tk apps:

      # Add menu bar $mainw->configure(-menu => my $menubar = $mainw->Menu); my $mbfile = $menubar->cascade(-label => "~File", -menuitems =>[ [ command => '~Open main log', -command => [\&log_window, "$log_dir/SwapClearLogFile.$da +te", 'Main log file' ]], [ command => '~Exit', -command => [$mainw, 'destroy']], [ command => '~Configure', -command => \&configure_window], [ command => '~Accept all failing components', -command => [\&run_command, 'tidyPidTable.ksh +']], ]); my $mbdebug = $mbfile->cascade( -label => "~Debug", #-title => 'Debug', -menuitems =>[ [ command => "Set all", -command => [\&debug_set_all, 1]], [ command => "Unset all", -command => [\&debug_set_all, 0]], ]); ... my %dbug; my $debug = 0; sub debug { my $tag = shift; unless (exists $dbug{$tag}) { $dbug{$tag} = $debug; $mbdebug->checkbutton( -label => $tag, -variable => \$dbug{$tag}); } $dbug{$tag}; } sub debug_set_all { $debug = shift; $dbug{$_} = $debug for keys %dbug; }

      Note that the list of checkbuttons on the debug menu is created dynamically, adding a new checkbutton each time debug() is called with a different parameter. Here's an example of my using the debug function from the same application:

      sub system_messages { print "system_messages called\n" if debug('system_messages'); my $fh; open $fh,"showSystemMessages|" or do {print "failed\n" if debu +g('Open pipe fail'); return;}; print "open succeeded\n" if debug('Open pipe succeed'); $mainw->fileevent($fh, 'readable', [\&get_message_counts, $fh] +); print "Return from fileevent\n" if debug('post fileevent'); }


      Oh Lord, wonít you burn me a Knoppix CD ?
      My friends all rate Windows, I must disagree.
      Your powers of persuasion will set them all free,
      So oh Lord, wonít you burn me a Knoppix CD ?
      (Missquoting Janis Joplin)

Re: Using the Perl Debugger (-d)
by johnnywang (Priest) on Jan 26, 2007 at 06:08 UTC
    To me, the debugger is indispensable, and I'd urge everyone to learn and use it.

    Besides using "perl -de 1" to test any code snippet, there are many cases where the debugger is much better than print (of course, I print too, and log with Log4Perl). For example, if a script gets an array of files to process, and something is not right for one of the files, it's so easy to run through the debugger and change the array on the fly than to change the code. And when you are handed someone else's code, going through the debugger will reveal much more of the flow than print.

    On a side note, I think php doesn't have as nice an interactive shell, it's one of the things I really miss when I do php.

Re: Using the Perl Debugger (-d)
by CountZero (Bishop) on Jan 26, 2007 at 07:10 UTC
    I use the debugger which is included in the KOMODO IDE. Depending on how you start your script, it can just run your code or it can single step through your code (with or without single stepping through sub-routines) or it can run your code and start single stepping once it reaches a "break-point". All the time when single stepping it shows the contents of all your variables which are in scope at that time.

    A truly great tool and a big help in solving the more difficult issues.

    Of course all this can be done with the Perl-debugger too: after all the KOMODO debugger is really the Perl debugger in disguise!


    "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

Re: Using the Perl Debugger (-d)
by eXile (Priest) on Jan 26, 2007 at 15:46 UTC
    I sometimes use something like:
    PERLDB_OPTS="NonStop=1 LineInfo=db.out AutoTrace" perl -d <script>
    which writes the flow of execution to a file (db.out in this case).
Re: Using the Perl Debugger (-d)
by Withigo (Friar) on Jan 27, 2007 at 00:50 UTC
    As far as a debugger tutorials, sure, the relevant perldocs are voluminous; but the few tutorials which I have managed to find demonstrate the same handful of examples which are mostly basic usage.

    If you want to do anything non-trivial with the debugger, or if you find yourself poking around the and source for whatever crazy reasons, or if you find yourself wanting to extend the debugger and/or customize parts of it, you're pretty much on your own.

    There was an engineer over at Yahoo who documented the debugger in much greater detail and clarity than in the perldocs(IMHO). Have a look at it here. I found it enormously useful in figuring out how the debugger works and in getting more out of the debugger.
      "There was an engineer over at Yahoo who documented the debugger in much greater detail and clarity than in the perldocs(IMHO)."

      That would be me, and thanks. I'm always glad to talk abut debugger internals (though I admit to still being kinda unclear about some of it. That's some pretty convoluted code), so /msg me if you like.

      As far as developing your own commands, I did a hack called Devel::Command that lets you play around with your own debugger commands. Essentially it patches DB::DB at startup to insert a check for user commands first. It's pretty easy to use. As an example, Devel::Command::Viz adds a viz command that uses GraphViz::Data::Structure to draw pretty pictures of your data (Unix-like systems only, but Windows patches really really welcome!).