Perl 如何(如果可能)将断点设置为特定的闭包?
当使用特定闭包的多个实例时,Perl调试器为每个实例列出相同的行号范围,而闭包实际上是不同的。 由于调试器的Perl 如何(如果可能)将断点设置为特定的闭包?,perl,debugging,closures,Perl,Debugging,Closures,当使用特定闭包的多个实例时,Perl调试器为每个实例列出相同的行号范围,而闭包实际上是不同的。 由于调试器的b命令的参数是行号,我想知道是否可以将断点设置为特定的闭包 考虑这个交互式示例: DB sub{my$s=$\[0];sub(){$s};} DB$s1=_s(1) DB$s2=_s(2) DB x$s1->() 0 1 DB x$s2->() 0 2 DB x$s1 0代码(0x55c7e8754958) ->&main::\uuuu ANON\uuuu在0中 DB x$s2 0代码
b
命令的参数是行号,我想知道是否可以将断点设置为特定的闭包
考虑这个交互式示例:
DB sub{my$s=$\[0];sub(){$s};}
DB$s1=_s(1)
DB$s2=_s(2)
DB x$s1->()
0 1
DB x$s2->()
0 2
DB x$s1
0代码(0x55c7e8754958)
->&main::\uuuu ANON\uuuu在0中
DB x$s2
0代码(0x55c7e8764990)
->&main::\uuuu ANON\uuuu在0中
因此,代码引用清楚地表明$s1
和$s2
是不同的。
现在,我可以在调用$s1
时设置断点吗
注
我的第一个版本尝试了subs($){…}
,导致语法错误。。。(可能是失控的多行;;字符串从第2行开始)
尝试调用s(1)
时。
因此,您似乎无法真正覆盖s/old/new/
;-)
另一个音符
如果在一行上设置断点,如
my$checker=sub($){…};
在子例程中(在闭包中使用闭包),然后每次将$checker
分配给时停止执行,但在调用闭包时不停止执行。
我的解决方法是像这样插入换行符(并将断点设置为…
行):
my$checker=sub($){
...
};
根据您的问题,解决方案可能是创建一个“修饰”函数,设置一个固定断点(并将其分配回$s1)
DB sub{my$s=$\[0];sub(){$s};}
DB x$s1=_s(1)
0代码(0x55c7dc96b3a8)
->代码(0x55c7dc96b3a8)是否在???
DB x$s1_nob=$s1
0代码(0x55c7dc96b3a8)
->&main::\uuuu ANON\uuuu在0中
DB x$s1=sub{$DB::single=1;$s1_nob->()}
0代码(0x55c7dc9f1260)
->&main::(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 x$s1->()
main::CODE(0x55c7dc9f1260)((eval30)[/usr/share/perl/5.26/perl5db.pl:738]:
2:$s1=sub{$DB::single=1;$s1_nob->()};
DB s
0 1
似乎您(调试器)无法将断点设置为闭包,即使它有一个名称(继续问题中的代码):
DB*{main::xxx}=\u s(33)
DB x xxx
0 33
DB*{main::yyy}=\u s(44)
DB x yyy
0 44
DB b xxx
未找到子例程main::xxx。
DB x ref\&xxx
0“代码”
DB sub zzz(){22}####让我们与“常规”子例程进行比较
DB x zzz
0 22
DB x ref\&zzz
0“代码”
我想Perl需要一个增强请求。根据@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
现在您使用第一个参数来定义单步执行,第二个参数是闭包,下面的参数将传递给闭包
但这仍然需要在调用闭包时修改代码(将
$f->($a,$b,$c)
替换为DEBUG($d,$f,$a,$b,$c)
)。还是不漂亮。这不太可能。从同一原型创建的所有闭包都共享同一个编译的操作树,并且它是操作树中设置断点的操作?如果是这样,您可以将行断点设置为那些非共享子节点。然而,当您想象共享闭包在不同类的十几个对象方法中使用时,这基本上意味着更改程序以进行调试。在另一个函数中包装我要研究的函数并重新分配它。顺便说一句,在创建位置设置断点并分配装饰器也可以完成这项工作。
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
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