2010-03-02 11 views

Odpowiedz

14

Istnieje wiele przydatnych, cor Narzędzia oparte na e i CPAN do generowania śledzenia stosu (jak ilustrują inne odpowiedzi). Jeśli jednak chcesz przetasować własne, sprawdź wbudowane caller. Możesz użyć tego, aby zejść ze stosu i zobaczyć dokładnie, co się dzieje.

+4

Uh, lub użyj 'Devel :: StackTrace'. – jrockway

+5

To jest dobra, inna opcja. Wymaga to jednak zewnętrznego modułu, który może lub nie może być atrakcyjny. Czemu po prostu nie napisać tego jako odpowiedzi, zamiast rezygnować? –

31

(od use Carp;) da ci pełny ślad stosu jako część błędu. Jeśli potrzebujesz go jako część czegoś, czego potrzebujesz, to wszystko, czego potrzebujesz, to confess.

za komentarze, oto wyjście różnych Carp funkcji:

use strict; 
use warnings; 
use Carp qw/longmess cluck confess/; 

sub foo { 
    &bar; 
} 

sub bar { 
    &baz; 
} 

sub baz { 
    shift->(); 
} 

my %tests = (
    'longmess' => sub { print longmess 'longmess' }, 
    'cluck' => sub { cluck 'using cluck' }, 
    'confess' => sub { confess 'using confess' }, 
); 

while (my ($name, $sub) = each %tests) { 
    print "$name - before eval:\n"; 
    eval { 
     foo($sub); 
    }; 
    print "$name - before if:\n"; 
    if ([email protected]) { 
     print "caught: [email protected]"; 
    } 
    print "$name - done\n\n"; 
} 

Uruchomienie tego skryptu, można uzyskać:

 
longmess - before eval: 
longmess at - line 14 
     main::baz called at - line 10 
     main::bar called at - line 6 
     main::foo('CODE(0x183a4d0)') called at - line 26 
     eval {...} called at - line 25 
longmess - before if: 
longmess - done 

confess - before eval: 
confess - before if: 
caught: using confess at - line 20 
     main::__ANON__() called at - line 14 
     main::baz called at - line 10 
     main::bar called at - line 6 
     main::foo('CODE(0x183a3e0)') called at - line 26 
     eval {...} called at - line 25 
confess - done 

cluck - before eval: 
using cluck at - line 19 
     main::__ANON__() called at - line 14 
     main::baz called at - line 10 
     main::bar called at - line 6 
     main::foo('CODE(0x183a434)') called at - line 26 
     eval {...} called at - line 25 
cluck - before if: 
cluck - done 

Uruchomienie tego skryptu, ale przekierowuje STDOUT (pokazując w ten sposób, co zostanie wydrukowane na STDERR) , otrzymujesz:

 
using cluck at - line 19 
     main::__ANON__() called at - line 14 
     main::baz called at - line 10 
     main::bar called at - line 6 
     main::foo('CODE(0x183a434)') called at - line 26 
     eval {...} called at - line 25 
+3

To wysyła ślad stosu i błąd do STDERR; jeśli chcesz go przechwycić, użyj bezpośrednio Carp :: longmess(). I Carp :: cluck jest jak wyznać, ale potem umiera. – ysth

+2

Myślę, że to wstecz - "cluck" to ostrzeżenie ze śladami stosu, a "wyznanie" to kostka. – mob

+0

err, yes, that was backwards – ysth

31

Dla potrzeb debugowania, podoba mi się Carp::Always.

perl -MCarp::Always my_script.pl 
+1

Wydaje się, że muszę to zrobić -MCarp = verbose – brianegge

9

Łatwy sposób korzystania z caller. Ten kod nie używa żadnego dodatkowego modułu. Po prostu umieść go tam, gdzie jest to potrzebne.

my $i = 1; 
print "Stack Trace:\n"; 
while ((my @call_details = (caller($i++)))){ 
    print $call_details[1].":".$call_details[2]." in function ".$call_details[3]."\n"; 
}