perl stack-trace callstack

¿Cómo puedo obtener una lista de pila de llamadas en Perl?



stack-trace callstack (7)

Este código funciona sin ningún módulo adicional . Solo inclúyelo donde sea necesario.

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

¿Hay alguna manera de que pueda acceder (para imprimir) una lista de sub + módulo a la profundidad arbitraria de sub llamadas que preceden a una posición actual en una secuencia de comandos de Perl?

Necesito hacer cambios en algunos módulos Perl (.pm''s). El flujo de trabajo se inicia desde una página web a través de un script cgi, pasando la entrada a través de varios módulos / objetos que terminan en el módulo donde necesito usar los datos. En algún momento, los datos se cambiaron y necesito averiguar dónde.


Puedes usar Devel::StackTrace .

use Devel::StackTrace; my $trace = Devel::StackTrace->new; print $trace->as_string; # like carp

Se comporta como la huella de Carp, pero puedes tener más control sobre los marcos.

El único problema es que las referencias están codificadas y si un valor referenciado cambia, no lo verá. Sin embargo, podrías mejorar algunas cosas con PadWalker para imprimir la información completa (sin embargo, sería enorme).


Si bien esto no responde a tu pregunta, podría ayudarte a resolver tu problema :-)

Aquí hay un artículo interesante que describe una forma de descubrir quién cambia sus variables de Mark Dominus


También hay Carp::confess y Carp::cluck .



caller puede hacerlo, aunque es posible que desee obtener más información que esa.


Carp::longmess hará lo que quieras, y es estándar.

use Carp qw<longmess>; use Data::Dumper; sub A { &B; } sub B { &C; } sub C { &D; } sub D { &E; } sub E { # Uncomment below if you want to see the place in E # local $Carp::CarpLevel = -1; my $mess = longmess(); print Dumper( $mess ); } A(); __END__ $VAR1 = '' at - line 14 main::D called at - line 12 main::C called at - line 10 main::B called at - line 8 main::A() called at - line 23 '';

Se me ocurrió este sub (¡Ahora con la acción de bendición opcional!)

my $stack_frame_re = qr{ ^ # Beginning of line /s* # Any number of spaces ( [/w:]+ ) # Package + sub (?: [(] ( .*? ) [)] )? # Anything between two parens /s+ # At least one space called [ ] at # "called" followed by a single space /s+ ( /S+ ) /s+ # Spaces surrounding at least one non-space character line [ ] (/d+) # line designation }x; sub get_stack { my @lines = split //s*/n/s*/, longmess; shift @lines; my @frames = map { my ( $sub_name, $arg_str, $file, $line ) = /$stack_frame_re/; my $ref = { sub_name => $sub_name , args => [ map { s/^''//; s/''$//; $_ } split //s*,/s*/, $arg_str ] , file => $file , line => $line }; bless $ref, $_[0] if @_; $ref } @lines ; return wantarray ? @frames : /@frames; }