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

Brethern,

I must be missing something about using the debugger

throop

Replies are listed 'Best First'.
Re: Debugger: I must be missing something
by grep (Monsignor) on Dec 08, 2006 at 17:18 UTC
    Setting breakpoints in other files - That's the way I do it. I have not heard of a better way. Just set a breakpoint at the point to step-in, step-in at that point and then set another break point when you're in the other file. There maybe another way but it hasn't been a big enough pain for me to look.

    Taming the printing of @_ — You're in a perl interpreter so, p $_[3]->{foo} will work. I also will use Data::Dumper; p Dumper \@_ in the debugger. I set my terminal to scoll 5000 lines to scroll over the result.

    Fumble fingers and stacktrace — I would setup another terminal window with a small script that runs the part of the regex you're interested in. You can w $data to get the current value being evaluated. Then test it in you other window.

    One key history — The debugger will repeat the last command if you just hit return.

    grep
    XP matters not. Look at me. Judge me by my XP, do you?

Re: Debugger: I must be missing something
by zentara (Cardinal) on Dec 08, 2006 at 17:43 UTC
    I find that using the Tk front end to the debugger, ptkdb, makes it all alot easier. It has a little separate window for watch variables, and lets you set break points so you can step thru the program. Google for "ptkdb tutorial" for a quick lesson.

    I'm not really a human, but I play one on earth. Cogito ergo sum a bum
Re: Debugger: I must be missing something
by grinder (Bishop) on Dec 08, 2006 at 21:54 UTC
    Setting breakpoints in other files
    f file2 # switch to viewing other file2 b 100 # set a breakpoint at file2:100 r # go!

    To delete a breakpoint in another file, use f to switch to viewing the source, and then run B 100 to remove it. Yes, it would be nice to be able to say B file2:100, but I have it on good authority that patching the debugger will drive you insane.

    One key history

    You must be missing a module. Term::ReadLine::Perl or something. Otherwise you would already have it.

    • another intruder with the mooring in the heart of the Perl

      An easy way to find the file that whatever::function is in: use %INC. This maps package names to file names.
      $ perl -de0 Loading DB routines from perl5db.pl version 1.28 Editor support available. Enter h or `h h' for help, or `man perldebug' for more help. main::(-e:1): 0 DB<1> x %INC 0 'warnings/register.pm' 1 '/usr/local/lib/perl5/5.8.8/warnings/register.pm' 2 'attributes.pm' 3 '/usr/local/lib/perl5/5.8.8/attributes.pm' 4 'XSLoader.pm' 5 '/usr/local/lib/perl5/5.8.8/darwin-2level/XSLoader.pm' 6 'IO/Handle.pm' 7 '/usr/local/lib/perl5/5.8.8/darwin-2level/IO/Handle.pm' 8 'Term/Cap.pm' 9 '/usr/local/lib/perl5/5.8.8/Term/Cap.pm' 10 'SelectSaver.pm' 11 '/usr/local/lib/perl5/5.8.8/SelectSaver.pm' 12 'Term/ReadLine/Perl.pm' 13 '/usr/local/lib/perl5/site_perl/5.8.8/Term/ReadLine/Perl.pm' 14 'warnings.pm' 15 '/usr/local/lib/perl5/5.8.8/warnings.pm' 16 'Carp/Heavy.pm' 17 '/usr/local/lib/perl5/5.8.8/Carp/Heavy.pm' 18 'Config.pm' 19 '/usr/local/lib/perl5/5.8.8/darwin-2level/Config.pm' 20 'Symbol.pm' 21 '/usr/local/lib/perl5/5.8.8/Symbol.pm' 22 'IO.pm' 23 '/usr/local/lib/perl5/5.8.8/darwin-2level/IO.pm' 24 'Carp.pm' 25 '/usr/local/lib/perl5/5.8.8/Carp.pm' 26 'Term/ReadLine.pm' 27 '/usr/local/lib/perl5/5.8.8/Term/ReadLine.pm' 28 'vars.pm' 29 '/usr/local/lib/perl5/5.8.8/vars.pm' 30 'strict.pm' 31 '/usr/local/lib/perl5/5.8.8/strict.pm' 32 'Exporter.pm' 33 '/usr/local/lib/perl5/5.8.8/Exporter.pm' 34 'Config_heavy.pl' 35 '/usr/local/lib/perl5/5.8.8/darwin-2level/Config_heavy.pl' 36 'Term/ReadLine/readline.pm' 37 '/usr/local/lib/perl5/site_perl/5.8.8/Term/ReadLine/readline.pm' 38 'Term/ReadKey.pm' 39 '/usr/local/lib/perl5/site_perl/5.8.8/darwin-2level/Term/ReadKey.p +m' 40 'AutoLoader.pm' 41 '/usr/local/lib/perl5/5.8.8/AutoLoader.pm' 42 'perl5db.pl' 43 '/usr/local/lib/perl5/5.8.8/perl5db.pl' 44 'DynaLoader.pm' 45 '/usr/local/lib/perl5/5.8.8/darwin-2level/DynaLoader.pm' 46 'SelfLoader.pm' 47 '/usr/local/lib/perl5/5.8.8/SelfLoader.pm' DB<2>
      Notice that the keys are module names (with slashes instead of double-colons) and the values are filenames. You can then use the debugger's f command to switch files. After that, all of the code navigation commands work fine in the new file. Do a '.' to get back to where you were previously.

      Edit: Devel::Command::NewF extends the f command to automatically look up the module in %INC, translating the name for you from Whatever::It::Is to Whatever/It/Is.pm, and loading the module if it isn't found.

      $ perl -de0 Patching with Devel::Command::DBSub::DB_5_8_5 Loading DB routines from perl5db.pl version 1.27 Editor support available. Enter h or `h h' for help, or `man perldebug' for more help. main::(-e:1): 0 DB<1> fx Test::More Loaded Test::More auto(-1) DB<2> f /home/y/lib/perl5/5.8/i386-freebsd-thread-multi/Test +/More.pm 1 package Test::More; 2 3: use 5.004; 4 5: use strict; 6 7 8 # Can't use Carp because it might cause use_ok() to accidentally + succeed9 # even though the module being used forgot to use Carp. + Yes, this 10 # actually happened. DB<3>
Re: Debugger: I must be missing something (few)
by tye (Sage) on Dec 09, 2006 at 07:28 UTC

    To set a breakpoint in another file, view some source in that file and then set the breakpoint. In your specific example, an easy way to do that would be:

    l package2::function2 b 100

    I often use x "@_" to get a summary of arguments without having to worry about some huge data structure being dumped.

    You can turn down the default "die reporting level" so that dieing, for whatever reason, doens't spew so much text: "O die=0". You might also want to turn down the warning reporting level: "O warn=0".

    - tye        

Re: Debugger: I must be missing something
by jbert (Priest) on Dec 08, 2006 at 18:16 UTC
    For emacs, open the script you want to debug and then Meta-x perldb<RET>. It's pretty nice. You get one frame with the normal debugger prompt and the other shows the source, current line of execution etc. You can also then use emacs text editing facilities on your perl debug history.

    Does anyone know of anything similar for vim? (looks like vim.org is having MySQL problems at the moment).

Re: Debugger: I must be missing something
by Popcorn Dave (Abbot) on Dec 08, 2006 at 18:06 UTC
    I have to second Zentara's comments about using ptkdb but I can offer one caveat. While it does a wonderful job moving through subroutines, make sure you don't try to move through a module's subroutine - unless it's one of your own - because you're going to see a lot of stuff that won't make sense. Just use step over instead of step in and you'll be fine.

    Besides that small niggle, I'd be lost without it in my toolkit.

    Revolution. Today, 3 O'Clock. Meet behind the monkey bars.
Re: Debugger: I must be missing something
by aufflick (Deacon) on Dec 11, 2006 at 12:06 UTC
    Extending grep's idea of using p Dumper ..., you can limit how big your output will be by setting $Data::Dumper::Maxdepth which limits how deep into the datastructure Data::Dumper will recurse.
Re: Debugger: I must be missing something
by sfink (Deacon) on Dec 11, 2006 at 18:19 UTC
    Taming the printing of @_

    Do it in stages. Avoid 'x' as long as you need to if there's a possibility of an enormous data structure:

    <DB> p "@_" ARRAY(0x38234) Big::Nested::Mess=HASH(0x382437) <DB> x keys %{ $_[1] } ...just the keys, so you can see what to look for...
    When I was doing this a lot, I defined a p() subroutine that made a recursive copy of complex data structures, only the copy was something much more readable. This is assuming that the big nasty data structure is your own, and you have some application-specific notion of what would be more or less interesting to see in the output.
    sub p { my $x = shift; if (! ref $x) { return $x; } elsif (ref($x) eq 'My::Class') { return bless { name => $x->{name}, manager => $x->{manager}->getId(), children => p($x->{children}), # add any other fields you want to see }, ref($x); } elsif (UNIVERSAL::isa($x, 'ARRAY')) { return [ map { p($_) } @$x ]; } elsif (UNIVERSAL::isa($x, 'HASH')) { return { map { $_ => p($x->{$_}) } keys %$x }; } else { return $x; } }
    ...tailored to your specific situation. (Actually, I think I also did a UNIVERSAL::can($x, 'p') to see if the object implemented its own readable-conversion method.)

    Then you can do 'x p($whatever)' and get your customized dump. (You can take this farther, and pass in a "brevity level" parameter that starts out zero to display everything, but increases as you get into further nested things so that they will display as one-line summaries rather than structural dumps.)