perltips
 

debugger tips

There are also times that you'd like to have a breakpoint set
programatically. One might be adding a '-d' switch to you own
program to set breakpoints at obvious points for debugging:

my @optionz = qw( debug+ );
my $cmdline = {};

GetOptions $cmdline, @optionz or die 'trying...';

my $debug = $cmdline->{debug};

...


$DB::single = 1 if $debug;

frobnicate $_ while <ARGV>;

...

sub frobnicate
{
my $line = shift;

$DB::single = 1 if $debug > 1;

...
}

The Perl debugger is written in Perl and lives in the DB
package. Its global variables are in the symbol table just like
any other package's and can be set by name. $DB::single is what
the debugger uses to tell itself to stop at the next line. You
can tell it to stop also. In this case if $debug is true the
code stops before frobnicat is called, if it's greater than one
then execution goes single-step for each of the lines being
called. You can use tests based on the data values, command line,
error status:

eval
{
};

# trace error handling only.

$DB::trace = 1 if $@;

The trace variable, as you probably guessed, turns on execution
tracing, which is what the 't' command toggles trace mode.

The one other thing you probably want to do occasionally is remove
the breaks. This is done with the 'd' command (for a particular
line or subroutine) or 'D' to delete all breakpoints. Using 'd'
with no line on it deletes the current line's breakpoint.

====

$DB::single=1 not so hard coded

There's a little known way to hard code breakpoints into the code. It's done by setting $DB::single. Usually you see it as "$DB::single = 1" but it's even less widely realized that it doesn't have to be 1. You can set it to any true value or expression! "$DB::single = $foo == 42" is "break when $foo is 42".

====


Flymake-mode

Emacs 22 comes with flymake-mode, which has a Perl interpreter to check your code on-the-fly. Great for checking your variables are defined and nothing is misspelled or anything.


====

Memory debugging:

To know where is your memory being allocated, you can use Devel::DumpSizes

then:

use Devel::DumpSizes;

foreach my $elem (@long_loop)  {

# sth 

    Devel::DumpSizes::dump_sizes("dump.txt");

}

you can then let it run and do a:

tail -f dump*my

to have a look at the growth in memory usage of your script

# it doesnt seem to work in debugging mode for me... 

====

More debugging tips:

  DB<37> h {
{ db_command    Define debugger command to run before each prompt.
{ ?            List debugger commands to run before each prompt.
{{ db_command    Add to the list of debugger commands to run before each prompt.
{ *             Delete the list of debugger commands to run before each prompt.

< ?            List Perl commands to run before each prompt.
< expr        Define Perl command to run before each prompt.
<< expr        Add to the list of Perl commands to run before each prompt.
< *                Delete the list of perl commands to run before each prompt.

b [line] [condition]
        Set breakpoint; line defaults to the current execution line;
        condition breaks if it evaluates to true, defaults to '1'.

b load filename Set breakpoint on 'require'ing the given file.
b postpone subname [condition]
        Set breakpoint at first line of subroutine after
        it is compiled.

b 23 (0 == ($count % 100)) #sets breakpoint every 100th $count


H -number    Display last number commands (default all).
H *          Delete complete history.

=====

To list the module directories being used:

x @INC

=====

To trace back the execution:

T        Stack trace.

t expr Traces through execution of expr

 

=====

When debugging a perl script, you can open a url in your local firefox/iceweasel with this command:

x system("iceweasel \"http://www.ensembl.org/Homo_sapiens/Gene/Splice?db=core;g=$gene_stable_id\"")

where $gene_stable_id is your variable