当前位置:  开发笔记 > 编程语言 > 正文

为什么这个Perl BEGIN块在调试器中的行为有所不同?

如何解决《为什么这个PerlBEGIN块在调试器中的行为有所不同?》经验,为你挑选了2个好方法。

我有一些在调试器外运行良好的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.)



1> brian d foy..:

这是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的引用.我认为这是处理$prevdieperl5db.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了.



2> Michael Carm..:

我认为任何时候代码在调试器中的行为都不同,这是一个错误.

您的问题可能与此有关:调试程序破坏了符号表的重置.从本质上讲,调试器似乎可以起到一些作用local- 可能是作为沙盒事物的一部分来提供交互性.显然,弄乱符号表会产生意想不到的副作用.我猜测调试器是本地化的$@,因此模糊了你的对象.我无法想到一个解决方法.

推荐阅读
夏晶阳--艺术
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有