代码之家  ›  专栏  ›  技术社区  ›  John Siracusa

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

  •  12
  • John Siracusa  · 技术社区  · 17 年前

    我有一些在调试器外部运行良好的Perl代码:

    % perl somefile.pl
    

    但当我在调试器中运行它时:

    % perl -d somefile.pl
    

    它的行为不同。

    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 ...
    

    $@ 当对象不是在调试器下运行时。相反,它是一个包含以下字符串的无lessed标量:

    " 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
    "
    

    (保留内部换行和间距。这是文字文本,甚至是“…”s。)

    我(最后)的问题是:我怎样才能让它工作?有解决办法吗?这是perl调试器模块中的错误吗?解决这个问题的最好办法是什么?(我知道这是几个问题,但它们都是相关的。)

    我在MacOSX10.5.5上使用Perl5.10.0。


    Adam Bellaire提出的dieLevel的建议看起来很有希望,事实上有些东西(不知道是什么)将它设置为1。但我使用一个 ~/.perldb ~/.perldb 文件:

    parse_options('dieLevel=0 warnLevel=0 signalLevel=0');
    

    o perl -de 0 而且在运行实际的 somefile.pl 文件


    perlbug 提交错误( RT 60890 )我已经开始洒了 local $SIG{'__DIE__'} perldoc perldebug 似乎仍然暗示着违约 dieLevel

    3 回复  |  直到 16 年前
        1
  •  14
  •   brian d foy    17 年前

    这是perl5db.pl创建的一个问题 __DIE__ $SIG{__DIE__} 在你的 eval

     eval { 
        local $SIG{__DIE__};
        die MyEx->new 
        };
    

    如果不这样做,您将从使用Carp::longmesss的DB::dbdie获取处理程序。如果dieLevel为0,则不应发生这种情况,但默认情况下它为1,如果未定义,则将其设置为1。这是2001年perl5db.pl的一个补丁,以前的默认值是0。

    您应该通过以下方式关闭此功能:

    PERLDB_OPT="dieLevel=0" perl5.10.0 -d program
    

    但在中仍然有一个代码引用 $SIG{{uuuu DIE} $prevdie 在perl5db.pl中 dieLevel

    # perl5db.pl dieLevel, around line 7777 
           elsif ($prevdie) {
                $SIG{__DIE__} = $prevdie;
                print $OUT "Default die handler restored.\n";
            }
    

    但请注意,在恢复 $SIG{{uuuu DIE} ,意味着里面的东西会泄露给另一个电话。当我运行该命令行时,在它处理之前有两个对dieLevel的调用 PERLDB_OPT 所以 $prevdie

    所以,在我不想再考虑perl5db.pl之前,这就是我所知道的。

        2
  •  5
  •   Michael Carman    17 年前

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

    可以 与此相关: Debugger corrupts symbol table munging local --大概是作为沙箱的一部分,以提供交互性。显然,弄乱符号表可能会产生意想不到的副作用。我猜调试器正在本地化 $@ 从而模糊了你的目标。我想不出有什么办法。

        3
  •  3
  •   Adam Bellaire    17 年前

    PERLDB_OPTS dieLevel 二级 Quote from here ).