如何修复DB :: goto框架?

时间:2016-01-04 16:09:30

标签: perl debugging stack-trace

当我将此脚本作为perl -d:DB t.pl运行时 $ cat t.pl

sub t { }
sub sb {
   goto &t;  # << The DB::goto is called from here
}
sb( a => 3 )

$ cat Devel / DB.pm

package DB;

BEGIN {
    $^P |= 0x80;
}

sub DB {
}

sub goto {
    local $"  =  ' - '; #"
    my $level =  0;
    while( my @frame = caller($level++) ) {
        print "@frame[0..3,5]\n";
    }
}

sub sub {
    return &$DB::sub;
}


1;
sub t { }
sub sb {
   goto &t;  # << The DB::goto is called from here
}
sb( a => 3 )

&#39;来电者&#39;调用表格DB :: goto返回下一个信息:

DB - Devel/DB.pm - 19 - DB::goto - 
main - t.pl - 5 - main::t - 

因为 DB :: goto被perl internals称为普通子,我期待下一个输出:

main - t.pl - 3 - DB::goto - 
main - t.pl - 5 - main::t - 

有可能修复这种行为吗?如果是的话 在哪个方向挖掘来修复它?

1 个答案:

答案 0 :(得分:1)

执行顺序是:

t.pl:5  sb( a => 3 )
  [enter DB::sub]
Devel/DB.pm:19  return &$DB::sub;
  [enter main::sb]
t.pl:3  goto &t;
  [enter DB::goto]

当达到goto时,最近的函数调用在第19行的Devel / DB.pm中,这样caller(0)返回的是什么。 (请记住,goto &NAME会改变调用堆栈。)

但听起来您想要报告调用goto的行号和文件。不幸的是,我不认为你可以使用caller执行此操作,因为caller甚至不知道goto

sub foo {
    goto &bar;
}

sub bar {
    print join ' - ', caller, "\n";
}

foo();

__END__
main - bar - 9 -  # line 9 is where foo() is called, not goto &bar

一种可能的解决方法是在DB::DB中存储上次执行的命令的文件名和行号,然后在DB::goto中的堆栈跟踪之前打印该值。不过,我还没有找到办法做到这一点。