有一个简单的脚本p.pl:
use strict;
use warnings;
our $x;
BEGIN {
$x = 42;
}
print "$x\n";
当我将其作为:
运行时perl -d:Trace p.pl
打印:
>> p.pl:3: our $x;
>> p.pl:7: print "$x\n";
42
如何打印BEGIN块语句,例如$x = 42;
?
因为我的意图不明确,所以加上澄清:
寻找任何在perl脚本运行时打印语句的方法(比如Devel :: Trace),但包括 BEGIN块中的语句。
答案 0 :(得分:8)
这很有可能。在早期$DB::single
块中设置BEGIN
。
use strict;
use warnings;
our $x;
BEGIN { $DB::single = 1 }
BEGIN {
$x = 42;
}
print "$x\n";
$DB::single
是一个调试器变量,用于确定是否在每一行调用DB::DB
函数。在编译阶段,它通常是错误的,但您可以在BEGIN
块的编译阶段进行设置。
当你想在标准调试器中调试编译时代码时,这个技巧也有助于在BEGIN
块内设置断点。
答案 1 :(得分:4)
免责声明:这只是尝试解释行为。
Devel :: Trace通过数据库模型连接到Perl debugging API。那只是代码。 It installs a sub DB::DB
。
最大的问题是,什么时候执行。根据{{3}},在执行期间有五种块类型在特定点执行。其中一个是BEGIN
,这是第一个。
考虑这个程序。
use strict;
use warnings;
our ($x, $y);
BEGIN { $x = '42' }
UNITCHECK { 'unitcheck' }
CHECK { 'check' }
INIT { 'init' }
END { 'end' }
print "$x\n";
这将输出以下内容:
>> trace.pl:8: INIT { 'init' }
>> trace.pl:3: our ($x, $y);
>> trace.pl:11: print "$x\n";
42
>> trace.pl:9: END { 'end' }
因此Devel :: Trace 看到 INIT
块和END
块。但为什么INIT
会阻止?
上面提到的perlmod说:
INIT块在Perl运行时开始执行之前以“先进先出”(FIFO)顺序运行。
显然在那个阶段,DB::DB
已经安装好了。我找不到任何说明完全运行sub
定义的文档。但是,它似乎是在BEGIN
之后和INIT
之前。因此,它没有看到BEGIN
中发生的任何事情。
在文件开头添加BEGIN { $Devel::Trace::TRACE = 1 }
也无济于事。
我在perldebug和喜欢的文档中翻找过,但找不到这种行为的解释。我的猜测是调试器接口根本不知道BEGIN
。毕竟它们很早就被执行了(例如perl -c -E 'BEGIN{ say "foo" } say "bar"'
会打印 foo 。)