如何说服Devel :: Trace打印BEGIN块语句?

时间:2015-07-01 13:10:48

标签: perl

有一个简单的脚本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块中的语句。

2 个答案:

答案 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 。)