我在尝试调试的 Perl 中的一个相当复杂的程序(在 Linux 下)遇到问题。我可以用这里的简单代码段来模拟问题(test.pl
):
use warnings;
use strict;
use feature qw/say/;
my @testa = ();
my $numelems = 10000;
# populate array/list of arrays
for (my $ix = 0; $ix < $numelems; $ix++) {
my @miniarr = ($ix, 1);
push(@testa, \@miniarr);
}
say "Array is now " . scalar(@testa) . " elements long";
my $BADnumelems = $numelems + 2;
my $sum = 0;
# loop through array/list of arrays
for (my $ix = 0; $ix < $BADnumelems; $ix++) {
my @minientry = @{$testa[$ix]};
$sum += $minientry[0];
}
say "Sum of elements is $sum";
运行此程序退出:
$ perl test.pl
Array is now 10000 elements long
Can't use an undefined value as an ARRAY reference at test.pl line 22.
所以,现在我想调试它——但是错误导致程序死掉,并退出调试器:
$ perl -d test.pl
Loading DB routines from perl5db.pl version 1.32
Editor support available.
Enter h or `h h' for help, or `man perldebug' for more help.
main::(test.pl:6): my @testa = ();
DB<1> c
Array is now 10000 elements long
Can't use an undefined value as an ARRAY reference at test.pl line 22.
at test.pl line 22
Debugged program terminated. Use q to quit or R to restart,
use o inhibit_exit to avoid stopping after program termination,
h q, h R or h o to get additional info.
DB<1> p $sum
DB<2> exit
$
然后,我在调试器(PerlMonks)中发现警告中断;所以我尝试添加这个:
...
use feature qw/say/;
$SIG{__DIE__} = sub { my($signal) = @_; say "DIEhandler: $signal"; $DB::single = 1; };
$SIG{__WARN__} = sub { my($signal) = @_; say "WARNhandler: $signal"; $DB::single = 1; };
my @testa = ();
...
...但这也会杀死调试器:
$ perl -d test.pl
Loading DB routines from perl5db.pl version 1.32
Editor support available.
Enter h or `h h' for help, or `man perldebug' for more help.
main::(test.pl:6): $SIG{__DIE__} = sub { my($signal) = @_; say "DIEhandler: $signal"; $DB::single = 1; };
DB<1> c
Array is now 10000 elements long
DIEhandler: Can't use an undefined value as an ARRAY reference at test.pl line 25.
Can't use an undefined value as an ARRAY reference at test.pl line 25.
Debugged program terminated. Use q to quit or R to restart,
use o inhibit_exit to avoid stopping after program termination,
h q, h R or h o to get additional info.
现在,问题是,我知道如果我用 Ctrl-C 中断程序 - 这通常会导致调试器进入单步模式;例如,您可以设置my $numelems = 100000000;
,并在它循环时按 Ctrl-C - 您可以调试:
$ perl -d test.pl
Loading DB routines from perl5db.pl version 1.32
Editor support available.
Enter h or `h h' for help, or `man perldebug' for more help.
main::(test.pl:6): $SIG{__DIE__} = sub { my($signal) = @_; say "DIEhandler: $signal"; $DB::single = 1; };
DB<1> c
^Cmain::(test.pl:14): my @miniarr = ($ix, 1);
DB<1> p $ix
148607
DB<2> q
现在,我可以在源 perl 程序中插入断点:
...
for (my $ix = 0; $ix < $BADnumelems; $ix++) {
$DB::single = 1; ### <=== BREAK HERE
my @minientry = @{$testa[$ix]};
...
但它在以下情况下进入循环$ix = 0
:
$ perl -d test.pl
Loading DB routines from perl5db.pl version 1.32
Editor support available.
Enter h or `h h' for help, or `man perldebug' for more help.
main::(test.pl:6): $SIG{__DIE__} = sub { my($signal) = @_; say "DIEhandler: $signal"; $DB::single = 1; };
DB<1> c
Array is now 10000 elements long
main::(test.pl:26): my @minientry = @{$testa[$ix]};
DB<1> p $ix
0
DB<2> q
...而且我不想通过 10000 个元素来解决有问题的部分:)
所以,我想到了以下几点——如果有一种方法可以从 Perl 脚本本身引发/生成/创建 SIGINT (Ctrl-C) ,那么我就可以从模具处理程序中引发它,并希望能引起一步在进程死亡之前的调试器。所以,我的问题是:
- 是否可以从 Perl 脚本中引发 SIGINT,这会破坏自身 - 如果是这样,如何?
- 如果前一个是可能的,它是否能够在进程终止之前使用模具处理程序中的 Ctrl-C 进入调试器步骤模式?
- 如果前一个是不可能的 - 我有什么可能导致进入调试器步骤模式,就在 program
die
s 的行?