繁体   English   中英

如何(如果可能)为特定的闭包设置断点?

[英]How to (if possible) set a breakpoint to a specific closure?

当使用特定闭包的多个实例时,Perl 调试器为每个实例列出相同的行号范围,而闭包实际上是不同的。 由于调试器的b命令的参数是行号,我想知道是否可以为特定的闭包设置断点。

考虑这个交互式示例:

  DB<13> sub _s($) { my $s = $_[0]; sub () { $s }; }
  DB<17> $s1 = _s(1)
  DB<18> $s2 = _s(2)
  DB<20> x $s1->()
0  1
  DB<21> x $s2->()
0  2
  DB<22> x $s1
0  CODE(0x55c7e8754958)
   -> &main::__ANON__ in 0
  DB<23> x $s2
0  CODE(0x55c7e8764990)
   -> &main::__ANON__ in 0

所以代码引用清楚地表明$s1$s2是不同的。 现在我可以在调用$s1时设置断点吗?

笔记

我的第一个版本尝试sub s($) { ... } ,导致syntax error ... (Might be a runaway multi-line ;; string starting on line 2)尝试调用s(1) 因此,您似乎无法真正覆盖s/old/new/ ;-)

另一个注意事项

如果你在像这样的行上设置断点

my $checker = sub ($) { ... };

在子例程中(使用闭包内的闭包),然后在每次分配$checker时停止执行,但不会在调用闭包时停止。 我的解决方法是插入这样的换行符(并将断点设置为...行):

my $checker = sub ($) {
    ...
};

根据您的问题,解决方案可能是创建一个设置固定断点的“装饰”函数(并将其分配回 $s1)。

DB<1> sub _s($) { my $s = $_[0]; sub () { $s }; }
DB<2> x $s1 = _s(1)
0  CODE(0x55c7dc96b3a8)
   -> &CODE(0x55c7dc96b3a8) in ???
DB<3> x $s1_nob = $s1
0  CODE(0x55c7dc96b3a8)
   -> &main::__ANON__ in 0
DB<4> x $s1 = sub {$DB::single=1; $s1_nob->()}
0  CODE(0x55c7dc9f1260)
   -> &main::__ANON__[(eval 30)[/usr/share/perl/5.26/perl5db.pl:738]:2] in (eval 30)[/usr/share/perl/5.26/perl5db.pl:738]:2-2
DB<6> x $s1->()
main::CODE(0x55c7dc9f1260)((eval 30)[/usr/share/perl/5.26/perl5db.pl:738]:2):
2:        $s1 = sub {$DB::single=1; $s1_nob->()};
DB<<7>> s
0  1

根据@Georg Mavridis 的回答,我尝试了这个:

  DB<1> sub _s($) { my $s = $_[0]; sub () { $s }; }

  DB<24> sub DEBUG($;$) { my ($f, $d) = @_; sub { $DB::single = $d; $f->() } }

  DB<27> x DEBUG(_s(1), 1)->()
main::CODE(0x5647d76c16d0)((eval 30)[/usr/lib/perl5/5.26.1/perl5db.pl:738]:2):
2:  sub DEBUG($;$) { my ($f, $d) = @_; sub { $DB::single = $d; $f->() } };
  DB<<28>> n
0  1
  DB<28> x DEBUG(_s(1), 0)->()
0  1

难看的是DEBUG调用了里面的闭包,所以必须知道闭包的参数。 所以我重新定义了它,改组了参数):

  DB<7> sub DEBUG($$;@) { my ($d, $f, @args) = @_; $DB::single = $d; $f->(@args) }

  DB<8> x DEBUG(1, _s(42))
main::DEBUG((eval 12)[/usr/lib/perl5/5.26.1/perl5db.pl:738]:2):
2:  sub DEBUG($$;@) { my ($d, $f, @args) = @_; $DB::single = $d; $f->(@args) };
  DB<<9>> n
0  42
  DB<9> x DEBUG(0, _s(42))
0  42

现在你使用第一个参数来定义单步执行,第二个参数是闭包,后面的参数传递给闭包。

但这仍然需要在调用闭包时修改代码(将$f->($a, $b, $c)替换为DEBUG($d, $f, $a, $b, $c) )。 还是不漂亮。

看来您(调试器)无法为闭包设置断点,即使它有一个名称(继续问题中的代码):

  DB<48> *{main::xxx} = _s(33)

  DB<49> x xxx
0  33
  DB<50> *{main::yyy} = _s(44)

  DB<51> x yyy
0  44
  DB<52> b xxx
Subroutine main::xxx not found.
  DB<55> x ref \&xxx
0  'CODE'
  DB<56> sub zzz() { 22 }  ### let's compare with a "regular" subroutine

  DB<57> x zzz
0  22
  DB<58> x ref \&zzz
0  'CODE'

我猜 Perl 需要一个增强请求。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM