How can I set a working breakpoint to a constant expression? - perl

I have Perl code that uses a constant with an initializing block like this:
use constant C => map {
...;
} (0..255);
When I try to set a breakpoint at the ...; line, it does not work, meaning: I can set the breakpoint, but the debugger does not stop there.
I tried:
Start the program with the debugger (perl -d program.pl)
Set the breakpoint in the debugger (b 2)
Reload using R, then run (r) the program
But still the debugger did not stop at the line, just as if I had no breakpoint set.
My Perl is not the latest; it's 5.18.2, just in case it matters...

You are trying to put a break point in a use block.
A use block is in effect a BEGIN block with a require in it.
The Perl debugger by default does not stop in compile phase.
However you can force the Perl debugger into single step mode inside a BEGIN block by setting the variable $DB::single to 1
See Debugging Compile-Time Statements in perldoc perldebug
If you change your code to
use constant C => map {
$DB::single = 1;
...;
} (0..255);
The Perl debugger will stop in the use statement.

You can avoid altering your code if you create a simple module like this (concept originated here):
package StopBegin;
BEGIN {
$DB::single=1;
}
1;
Then, run your code as
perl -I./ -MStopBegin -d test.pl
Pertinent Answer (previous, not-so-pertinent answer is below this one)
If test.pl looks like this:
use constant C => {
map {;
"C$_" => $_;
} 0 .. 255
};
here's what the debug interaction looks like:
% perl -I./ -MStopBegin -d test.pl
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.
StopBegin::CODE(0x55db6287dac0)(StopBegin.pm:8):
8: 1;
DB<1> s
main::CODE(0x55db6287db38)(test.pl:5):
5: };
DB<1> -
1 use constant C => {
2: map {;
3: "C$_" => $_;
4 } 0 .. 255
5==> };
DB<2> b 3
DB<3> c
main::CODE(0x55db6287db38)(test.pl:3):
3: "C$_" => $_;
DB<3>
Note the use of the breakpoint to stop inside the map.
Previous, Not-So-Pertinent Answer
If test.pl looks like this:
my $foo;
BEGIN {
$foo = 1;
};
here's what the debug interaction looks like:
% perl -I./ -MStopBegin -d test.pl
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.
StopBegin::CODE(0x5567e3d79a80)(StopBegin.pm:8):
8: 1;
DB<1> s
main::CODE(0x5567e40f0db0)(test.pl:4):
4: $foo = 1;
DB<1> s
main::(test.pl:1): my $foo;
DB<1> s
Debugged program terminated. Use q to quit or R to restart,
use o inhibit_exit to avoid stopping after program termination,
h q, h R or h o to get additional info.
DB<1>
Note the use of the s command to advance, otherwise it'll skip over the BEGIN block in test.pl

Related

Error in perl code - "Bizarre copy of ARRAY in leave at "

I am having one problem in this perl code.
It is showing some error "Bizarre copy of ARRAY in leave at " . Although code is correct, I feel. Can anybody help.
#!/usr/bin/perl -w
use strict;
sub getStatus() {
#my $self = shift;
my $status;
my #details;
my $Up = 2;
my $Down = 3;
$status = "Failed";
push #details, $Up, $Down;
my $detailMsg = join(",", #details);
return [$status, $detailMsg];
}
my $info = &getStatus();
my $status = ${#$info}[0];
my $detailMsg = ${#$info}[1];
print $status;
print $detailMsg;
exit 0;
-----------------------
Now debugging using perl -d option.
-----------------------
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::(test.pl:19): my $info = &getStatus();
DB<1> n
main::(test.pl:20): my $status = ${#$info}[0];
DB<1> n
main::(test.pl:20): my $status = ${#$info}[0];
DB<1> n
Bizarre copy of ARRAY in leave at test.pl line 20.
at test.pl line 20
Debugged program terminated. Use q to quit or R to restart,
use o inhibit_exit to avoid stopping after program termination,
h q, h R or h o to get additional info.
DB<1>
Please suggest any solution. If this is related to problem in perl module, then how can we overcome. Please suggest.
${#$info}[0] is an abomination. $info is the return value of your getStatus sub. It is an array reference. Then, #$info is the dereferenced array. But, you are evaluating it in scalar context, so it evaluates to 2. Then you try to evaluate that as an array reference, and take its first element.
Bizarre indeed. The error message is very appropriate.
PS: Don't use &getStatus(). getStatus() is the right way to invoke your sub.
PPPS: You probably do want $info->[0], but then it is hard to be certain, because what you wrote is so bizarre.

What is the role of the BEGIN block in Perl?

I know that the BEGIN block is compiled and executed before the main body of a Perl program. If you're not sure of that just try running the command perl -cw over this:
#!/ms/dist/perl5/bin/perl5.8
use strict;
use warnings;
BEGIN {
print "Hello from the BEGIN block\n";
}
END {
print "Hello from the END block\n";
}
I have been taught that early compilation and execution of a BEGIN block lets a programmer ensure that any needed resources are available before the main program is executed.
And so I have been using BEGIN blocks to make sure that things like DB connections have been established and are available for use by the main program. Similarly, I use END blocks to ensure that all resources are closed, deleted, terminated, etc. before the program terminates.
After a discussion this morning, I am wondering if this the wrong way to look at BEGIN and END blocks.
What is the intended role of a BEGIN block in Perl?
Update 1: Just found out why the DBI connect didn't work. After being given this little Perl program:
use strict;
use warnings;
my $x = 12;
BEGIN {
$x = 14;
}
print "$x\n";
when executed it prints 12.
Update 2: Thanks to Eric Strom's comment below this new version makes it clearer:
use strict;
use warnings;
my $x = 12;
my $y;
BEGIN {
$x = 14;
print "x => $x\n";
$y = 16;
print "y => $y\n";
}
print "x => $x\n";
print "y => $y\n";
and the output is
x => 14
y => 16
x => 12
y => 16
Once again, thanks Eric!
While BEGIN and END blocks can be used as you describe, the typical usage is to make changes that affect the subsequent compilation.
For example, the use Module qw/a b c/; statement actually means:
BEGIN {
require Module;
Module->import(qw/a b c/);
}
similarly, the subroutine declaration sub name {...} is actually:
BEGIN {
*name = sub {...};
}
Since these blocks are run at compile time, all lines that are compiled after a block has run will use the new definitions that the BEGIN blocks made. This is how you can call subroutines without parenthesis, or how various modules "change the way the world works".
END blocks can be used to clean up changes that the BEGIN blocks have made but it is more common to use objects with a DESTROY method.
If the state that you are trying to clean up is a DBI connection, doing that in an END block is fine. I would not create the connection in a BEGIN block though for several reasons. Usually there is no need for the connection to be available at compile time. Performing actions like connecting to a database at compile time will drastically slow down any editor you use that has syntax checking (because that runs perl -c).
Have you tried swapping out the BEGIN{} block for an INIT{} block? That's the standard approach for things like modperl which use the "compile-once, run-many" model, as you need to initialize things anew on each separate run, not just once during the compile.
But I have to ask why it's all in special block anyway. Why don't you just make some sort of prepare_db_connection() function, and then call it as you need to when the program starts up?
Something that won't work in a BEGIN{} will also have the same problem if it's main-line code in a module file that gets used. That's another possible reason to use an INIT{} block.
I've also seen deadly-embrace problems of mutual recursion that have to be unravelled using something like an require instead of use, or an INIT{} instead of a BEGIN{}. But that's pretty rare.
Consider this program:
% cat sto-INIT-eg
#!/usr/bin/perl -l
print " PRINT: main running";
die " DIE: main dying\n";
die "DIE XXX /* NOTREACHED */";
END { print "1st END: done running" }
CHECK { print "1st CHECK: done compiling" }
INIT { print "1st INIT: started running" }
END { print "2nd END: done running" }
BEGIN { print "1st BEGIN: still compiling" }
INIT { print "2nd INIT: started running" }
BEGIN { print "2nd BEGIN: still compiling" }
CHECK { print "2nd CHECK: done compiling" }
END { print "3rd END: done running" }
When compiled only, it produces:
% perl -c sto-INIT-eg
1st BEGIN: still compiling
2nd BEGIN: still compiling
2nd CHECK: done compiling
1st CHECK: done compiling
sto-INIT-eg syntax OK
While when compiled and executed, it produces this:
% perl sto-INIT-eg
1st BEGIN: still compiling
2nd BEGIN: still compiling
2nd CHECK: done compiling
1st CHECK: done compiling
1st INIT: started running
2nd INIT: started running
PRINT: main running
DIE: main dying
3rd END: done running
2nd END: done running
1st END: done running
And the shell reports an exit of 255, per the die.
You should be able to arrange to have the connection happen when you need it to, even if a BEGIN{} proves too early.
Hm, just remembered. There's no chance you're doing something with DATA in a BEGIN{}, is there? That's not set up till the interpreter runs; it's not open to the compiler.
While the other answers are true, I find it also worth to mention the use of BEGIN and END blocks when using the -n or -p switches to Perl.
From http://perldoc.perl.org/perlmod.html
When you use the -n and -p switches to Perl, BEGIN and END work just as they do in awk, as a degenerate case.
For those unfamiliar with the -n switch, it tells Perl to wrap the program with:
while (<>) {
... # your program goes here
}
http://perldoc.perl.org/perlrun.html#Command-Switches if you're interested about more specific information about Perl switches.
As an example to demonstrate the use of BEGIN with the -n switch, this Perl one-liner enumerates the lines of the ls command:
ls | perl -ne 'BEGIN{$i = 1} print "$i: $_"; $i += 1;'
In this case, the BEGIN-block is used to initiate the variable $i by setting it to 1 before processing the lines of ls. This example will output something like:
1: foo.txt
2: bar.txt
3: program.pl
4: config.xml

How can I monitor the Perl call stack?

I'm using ActivePerl 5.8 on Windows XP.
use strict;
use warnings;
use Data::Dumper;
There are three subroutines used in my script.
To detect the call stack, I can only insert some print "some location"; and check the print result from console Window.
Is there any good method to monitor it? Thank you.
If it's your code, you might want to use:
Carp::cluck( "And here's the stack:" );
See Carp::cluck. It prints out a warning with a stack trace. It works like the "printf" style of debug output.
Use the debugger's T command.
Example:
$ perl -d -e'
sub foo {}
sub bar { foo; }
bar;
'
Loading DB routines from perl5db.pl version 1.32
Editor support available.
Enter h or `h h' for help, or `man perldebug' for more help.
main::(-e:4): bar;
DB<1> s
main::bar(-e:3): sub bar { foo; }
DB<1> s
main::foo(-e:2): sub foo {}
DB<1> T
. = main::foo() called from -e line 3
. = main::bar() called from -e line 4
DB<1> s
Debugged program terminated. Use q to quit or R to restart,
use o inhibit_exit to avoid stopping after program termination,
h q, h R or h o to get additional info.
DB<1> q
You weren't specific about why you'd like to monitor the call stack and trace your subs, so answers will have to be broad.
One method is caller:
caller
Returns the context of the current subroutine call. In scalar context, returns the caller's package name if there is a caller, that is, if we're in a subroutine or eval or require, and the undefined value otherwise. In list context, returns
# 0 1 2
($package, $filename, $line) = caller;
With EXPR, it returns some extra information that the debugger uses to print a stack trace. The value of EXPR indicates how many call frames to go back before the current one.
# 0 1 2 3 4
($package, $filename, $line, $subroutine, $hasargs,
# 5 6 7 8 9 10
$wantarray, $evaltext, $is_require, $hints, $bitmask, $hinthash)
= caller($i);
You might also use the Devel::Cover module:
Code coverage data are collected using a pluggable runops function which counts how many times each op is executed. These data are then mapped back to reality using the B compiler modules. There is also a statement profiling facility which needs a better backend to be really useful.
The more you tell us about what you want to do, the more helpful to you our answers will be!
You rarely need to directly manage the call stack in Perl. If you do caller is the tool you want. However, it is only rarely needed.
More often, I want to see a stack trace when I am debugging. Good news, its easy to get a stack trace, simply use Carp's confess and cluck functions instead of die and warn.
use strict;
use warnings;
use Carp;
bar(6.1);
bar(1);
sub foo {
confess "Oh noes" unless #_ == 6; # confess is fatal
}
sub bar {
my $count = shift;
cluck "bar is in trouble" unless int $count == $count; # cluck is not fatal
foo( ('a')x $count );
}
This gets you:
dao:~ toad$ perl test.pl
bar is in trouble at test.pl line 14
main::bar(6.1) called at test.pl line 5
Oh noes at test.pl line 9
main::foo('a') called at test.pl line 15
main::bar(1) called at test.pl line 6

How do I rerun a subroutine without restarting the script in Perl's debugger?

Suppose I have a situation where I'm trying to experiment with some Perl code.
perl -d foo.pl
Foo.pl chugs it's merry way around (it's a big script), and I decide I want to rerun a particular subroutine and single step through it, but without restarting the process. How would I do that?
The debugger command b method sets a breakpoint at the beginning of your subroutine.
DB<1> b foo
DB<2> &foo(12)
main::foo(foo.pl:2): my ($x) = #_;
DB<<3>> s
main::foo(foo.pl:3): $x += 3;
DB<<3>> s
main::foo(foo.pl:4): print "x = $x\n";
DB<<3>> _
Sometimes you may have to qualify the subroutine names with a package name.
DB<1> use MyModule
DB<2> b MyModule::MySubroutine
just do: func_name(args)
e.g.
sub foo {
my $arg = shift;
print "hello $arg\n";
}
In perl -d:
DB<1> foo('tom')
hello tom
Responding to the edit regarding wanting to re-step through a subroutine.
This is not entirely the most elegant way of doing this, but I don't have another method off the top of my head and am interested in other people's answers to this question :
my $stop_foo = 0;
while(not $stop_foo) {
foo();
}
sub foo {
my $a = 1 + 1;
}
The debugger will continually execute foo, but you can stop the next loop by executing '$stop_foo++' in the debugger.
Again, I don't really feel like that's the best way but it does get the job done with only minor additions to the debugged code.

How do I move the instruction point in the Perl debugger?

I would like to be able to (reasonably) arbitrarily set my execution point in the Perl debugger. E.g., moving immediately prior to an if from the body of the if and setting a variable.
Rummaging around the perldebug(and perldebguts and the perl debugger POD) page suggests that this kind of functionality is either not supported or not documented.
A cumbersome workaround would be to add labels and conditional goto statements throughout your code. But depending on how badly you want to emulate this feature, it might be worth it.
POINT1: $GOTO=""; # $GOTO is our fake variable that we only set from the debugger
($a,$b,$c)=(1,2,3);
POINT2: $GOTO="";
if ($a < $b) {
goto $GOTO if $GOTO;
if ($a > $c) {
goto $GOTO if $GOTO;
print "foo\n";
} else {
goto $GOTO if $GOTO;
print "bar\n";
}
goto $GOTO if $GOTO;
} else {
goto $GOTO if $GOTO;
print "nothing\n";
goto $GOTO if $GOTO;
}
Sample debugging session:
$ perl -d debuggoto.pl
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::(debuggoto.pl:1): POINT1: $GOTO=""; # $GOTO is our fake variable that we only set from the debugger
DB<1> n
main::(debuggoto.pl:2): ($a,$b,$c)=(1,2,3);
DB<1>
main::(debuggoto.pl:3): POINT2: $GOTO="";
DB<1>
main::(debuggoto.pl:4): if ($a < $b) {
DB<1>
main::(debuggoto.pl:5): goto $GOTO if $GOTO;
DB<1>
main::(debuggoto.pl:6): if ($a > $c) {
DB<1>
main::(debuggoto.pl:10): goto $GOTO if $GOTO;
DB<1>
main::(debuggoto.pl:11): print "bar\n";
DB<1>
bar
main::(debuggoto.pl:13): goto $GOTO if $GOTO;
DB<1> $GOTO="POINT2"
DB<2> n
main::(debuggoto.pl:3): POINT2: $GOTO="";
DB<2> $c=0
DB<3> n
main::(debuggoto.pl:4): if ($a < $b) {
DB<3>
main::(debuggoto.pl:5): goto $GOTO if $GOTO;
DB<3>
main::(debuggoto.pl:6): if ($a > $c) {
DB<3>
main::(debuggoto.pl:7): goto $GOTO if $GOTO;
DB<3>
main::(debuggoto.pl:8): print "foo\n";
DB<3>
foo
main::(debuggoto.pl:13): goto $GOTO if $GOTO;
DB<3>
Debugged program terminated. Use q to quit or R to restart,
use o inhibit_exit to avoid stopping after program termination,
h q, h R or h o to get additional info.
DB<3>
Use `q' to quit or `R' to restart. `h q' for details.
DB<3>
I wonder if it would be possible to build a debugger that uses this idea.
I am still not sure what exactly this would achieve, but I bet a custom runloop that skips ops you don't care about until you start caring again might solve your problem.
A good runloop to cargo-cult is Runops::Switch. Remove the switch statement and write a function that skips ops until you are on the one you want to run; then just call into the normal runloop to actually run that op.
Relevant code: http://cpansearch.perl.org/src/RGARCIA/Runops-Switch-0.04/Switch.xs
This is all handwaving, I have never written a runloop before. The goto idea in another post is also good, but this involves writing less code.
Breakpoints can only be set on the first line of a statement.
This can't be done with the existing debugger.