Примечание Это было написано по оригинальному вопросу, прежде чем оно было изменено. Он извлекает все лексические переменные для каждого фрейма в стеке вызовов в точке, где выбрано die
без отладчика.
Для отладки Carp::Always полезно.
Кроме того, за ошибки, вы, кажется, после того, как вы можете переопределить die
получить Carp
«s трассировку
eval {
local $SIG{__DIE__} = \&Carp::confess;
# ... code ...
};
if ([email protected]) { print [email protected] }
Это имеет ограничения и сложности, чтобы быть в курсе, см eval и %SIG in perlvar и die, но учитывая отсутствие подробностей о том, что вызывает ошибку, стоит попробовать.
С __DIE__
работает крюк, когда die
срабатывает, в нем можно просматривать стек вызовов «вживую».
Код ниже использует caller, чтобы пройти стек и для базовой информации, и PadWalker получить лексические переменные для каждого кадра. Переменные в подсистемах существуют так, чтобы легче отслеживать результат.
use warnings;
use strict;
use PadWalker qw(peek_my);
my $ondie = sub {
my $sf = 0;
while (my @call = caller($sf)) { # go through stack frames
say "At $sf frame, |@call[0..3]|";
my $vars = peek_my($sf); # lexicals for this frame
for (keys %$vars) {
if (ref($vars->{$_}) eq 'SCALAR') {
print "\t$_ => ${$vars->{$_}}\n";
} elsif (not /^\$vars$/) {
print "\t$_ => $vars->{$_}\n";
}
}
++$sf;
}
};
eval {
local $SIG{__DIE__} = $ondie;
top_level(25);
};
if ([email protected]) { print "eval: [email protected]" }
sub top_level {
my ($top_x, $sub_name) = (12.1, (caller(0))[3]);
next_level($_[0]);
};
sub next_level {
my ($next_x, $sub_name) = (7, (caller(0))[3]);
$_[0]/0;
};
Выход
At 0 frame, |main debug_stack.pl 51 main::__ANON__|
$sf => 0
@call => ARRAY(0x15464c8)
At 1 frame, |main debug_stack.pl 59 main::next_level|
$next_x => 7
$ondie => REF(0x1587938)
$sub_name => main::next_level
At 2 frame, |main debug_stack.pl 38 main::top_level|
$top_x => 12.1
$ondie => REF(0x1587938)
$sub_name => main::top_level
At 3 frame, |main debug_stack.pl 36 (eval)|
$ondie => REF(0x1587938)
eval: Illegal division by zero at debug_stack.pl line 51.
В PadWalker в peek_my
возвращает hashref, где каждое значение является ссылкой. Я разыскиваю только скаляры, для демонстрации, а также исключаю $vars
, где выводы PadWalker
хранятся в печати. Чтобы оставить обработчик, начинайте с my $sf = 1
.
Я вижу. Я думал, что с отладчиком perl можно было бы поднимать/опускать стек вызовов, как можно с помощью отладчика python (с директивами 'up' /' down') и, следовательно, иметь возможность проверять лексические переменные на каждом уровне. Если вы правильно поняли, все, что вы можете сделать, это просмотреть обратную трассировку. Пожалуйста, поправьте меня, если я ошибаюсь. – kjo
@kjo: Боюсь, это правильно. Если вы посмотрите раздел BUGS ['perldoc perldebug'] (http://perldoc.perl.org/perldebug.html#BUGS), он говорит: *** Вы не можете получить информацию о кадре стека или в любых способах отладки моды, которые были не скомпилированные Perl, например, из расширений C или C++. *** Я бы не назвал это ошибкой, но довольно ясно, что в настоящее время недоступно то, что вы хотите. – Borodin
@kjo: Вот почему я описал, как создать автоматическую обратную трассировку в случае исключения. – Borodin