我有一些在调试器外运行良好的Perl代码:
% perl somefile.pl
但是当我在调试器中运行它时:
% perl -d somefile.pl
它的表现不同.
有问题的文件(有几个)是大型Perl模块的测试套件的一部分(~20K代码行).测试在编译时进行了大量的设置工作并使用BEGIN块.这是一些最小的复制代码:
BEGIN { package MyEx; sub new { bless {}, shift } package main; eval { die MyEx->new }; if($@) { die "Really die" unless($@->isa('MyEx')); } } print "OK\n";
如果你把它放入somefile.pl
并运行它,它按预期打印"OK".如果你在调试器中运行它perl -d somefile.pl
,它就会因为这个错误而死掉:
Can't call method "isa" without a package or object reference ...
结果是$@
代码在调试器下运行时不是对象.相反,它是一个包含此字符串的未标记的标量:
" at somefile.pl line 9 eval {...} called at somefile.pl line 9 main::BEGIN() called at somefile.pl line 16 eval {...} called at somefile.pl line 16 "
(保留内部换行符和间距.这是文字文本,甚至是"......".)
我需要这样的代码在调试器中运行.在测试套件中使用调试器是我工作流程的重要部分.该模块使用异常对象并在编译时执行大量操作,并期望在捕获时将对象抛出为对象.
我的问题(最后)是:我怎样才能使这个工作?有解决方法吗?这是perl调试器模块中的错误吗?解决问题的最佳方法是什么?(我知道这几个问题,但它们都是相关的.)
我在Mac OS X 10.5.5上使用perl 5.10.0.
Adam Bellaire建议的dieLevel看起来很有希望,而且确实有些东西(不知道是什么)让我为它设置为1.但我使用~/.perldb
文件将其设置为0 ,问题仍然存在.实际上,我将所有三个相关设置都设置为0.我的~/.perldb
文件:
parse_options('dieLevel=0 warnLevel=0 signalLevel=0');
我通过o
在调试器中运行命令确认设置有效.我看到它们在运行时perl -de 0
以及运行实际somefile.pl
文件时都设置为0 .
谢谢,布莱恩.我曾经perlbug
提交过一个错误(RT 60890),我已经开始local $SIG{'__DIE__'}
在代码中的所有适当位置撒上.(我也在bug中注意到,perldoc perldebug
似乎仍暗示默认dieLevel
值为0.)
这是perl5db.pl创建__DIE__
处理程序的问题.如果我本地化$SIG{__DIE__}
,你的eval
工作就像你期望的那样.
eval { local $SIG{__DIE__}; die MyEx->new };
如果你不这样做,你将从DB :: dbdie获得处理程序,它使用Carp :: longmess.如果dieLevel为0,则不会发生这种情况,但默认情况下为1,如果未定义,则设置为1.这是2001年perl5db.pl的补丁,之前的默认值为0.
你应该把它关掉:
PERLDB_OPT="dieLevel=0" perl5.10.0 -d program
但是之后仍然有一个代码引用$SIG{__DIE__}
,它是对dbdie的引用.我认为这是处理$prevdie
perl5db.pl中的全局变量的一个错误dieLevel
.在该子程序结束时,有:
# perl5db.pl dieLevel, around line 7777 elsif ($prevdie) { $SIG{__DIE__} = $prevdie; print $OUT "Default die handler restored.\n"; }
但请注意,在恢复之后$SIG{__DIE__}
,它会保留之前的值$prevdie
,这意味着其中的任何内容泄漏到另一个调用.当我运行该命令行时,在处理之前有两次调用dieLevel PERLDB_OPT
,因此$prevdie
可能很脏.
所以,就我所知,我不想再考虑perl5db.pl了.
我认为任何时候代码在调试器中的行为都不同,这是一个错误.
您的问题可能与此有关:调试程序破坏了符号表的重置.从本质上讲,调试器似乎可以起到一些作用local
- 可能是作为沙盒事物的一部分来提供交互性.显然,弄乱符号表会产生意想不到的副作用.我猜测调试器是本地化的$@
,因此模糊了你的对象.我无法想到一个解决方法.