![](/img/trans.png)
[英]Is it possible to set a breakpoint in the Perl debugger without modifying the source?
[英]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.