Using the debugger feature of Perl to add a breakpoint to our code we can even debug code that is executed during compilation.

Using the BEGIN block Perl allows us to write code that will be executed even before the rest of the code is compiled. It is rarely needed, but it is a very powerful tool.

However if you try to use the built-in debugger of Perl you will notice that the first statement it stops at is the first statement in your main code. By that time it already executed or tried to execute the BEGIN blocks.

How can you debug that code?

Debug code in BEGIN-block

In this rather stupid example we have a few statements in the BEGIN block

examples/begin_block_code.pl


my $z = 1;
my $q = 23;
print "DONE\n";


BEGIN {
    # $DB::single = 1;
    my $welcome = 'Hello World';
    my $n = 19+23;
    print "$welcome $n\n";
}

If I run this normally:

$ perl begin_block_code.pl

I get the expected output:

Hello World 42
DONE

If I run it with the debugger:

$ perl -d begin_block_code.pl

I get the debugger prompt, but as you can observe, it already printed the "Hello World 42" that comes from the BEGIN block.

examples/begin_block_code_1.txt


Loading DB routines from perl5db.pl version 1.53
Editor support available.

Enter h or 'h h' for help, or 'man perldebug' for more help.

Hello World 42
main::(begin_block_code.pl:2):  my $z = 1;
  DB<1>

Adding an enabling the following line:

$DB::single = 1;

as the first statement of the BEGIN-block will tell the debugger, to stop at that point and let you debug:

$ perl -d begin_block_code.pl

examples/begin_block_code_2.txt


Loading DB routines from perl5db.pl version 1.53
Editor support available.

Enter h or 'h h' for help, or 'man perldebug' for more help.

main::CODE(0x55c169ea9dd0)(begin_block_code.pl:8):
8:    my $welcome = 'Hello World';
  DB<1>

Here you can see that the next statement to be executed is the first statement of the BEGIN-block.

Debugging code in the body of a module

In this example we don't have a BEGIN block. We have something much less obvious. We have a module that has code outside of any function definition:

examples/Factorial.pm

package Factorial;
use strict;
use warnings;

$DB::single = 1;
print("Doing some stuff here\n");

sub factorial {
    my ($n) = @_;
    my $fact = 1;
    $fact *= $_ for 1..$n;
    return $fact;
}

print("Doing some other stuff here\n");

1;



We then have a script that uses that module.

examples/use_factorial.pl

use strict;
use warnings;

use lib '.';

print("Before use\n");

use Factorial;

print(Factorial::factorial(4), "\n");

The use lib '.'; is necessary as recent version of Perl have removed the current directory from the list of places where perl looks for modules.

Then we print a line "before" we "use" the module.

Running the script gives us this:

Doing some stuff here
Doing some other stuff here
Before use
24

The key issue here is that the code in the body of the module, the two print statements, were executed before the print-statemen that is located before the "use"-statement.

How can this happen?

A use statement adds an implicit BEGIN-block that is executed during compile time.

Just as with explicit BEGIN-blocks we can add

$DB::single = 1;

Then if we run the code using the buit-in debugger:

perl -d use_factorial.pl

It will pause execution at that assignment statement. Then we can use the regular instructions of the debugger to look around and to make progress.