Getting stack traces in Perl?

20,600

Solution 1

There are many useful, core and CPAN based tools to generate a stack trace (as other answers illustrate.) However, if you want to roll your own, check out the caller builtin. You can use this to walk down the stack and see exactly what's happening.

Solution 2

For debugging needs, I like Carp::Always.

perl -MCarp::Always my_script.pl

Solution 3

Carp::confess (from use Carp;) will give you a full stack trace as part of the error. If you just need it as part of something failing, confess is all you really need.

Per comments, here's output of various Carp functions:

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 ($@) {
        print "caught: $@";
    }
    print "$name - done\n\n";
}

Running this script, you get:

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

Running this script but redirecting STDOUT (thus showing what gets printed on STDERR), you get:

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

Solution 4

Easy way using caller. This code does not use any additional module. Just include it where needed.

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";
}
Share:
20,600

Related videos on Youtube

Timmy
Author by

Timmy

timmy.

Updated on July 09, 2022

Comments

  • Timmy
    Timmy almost 2 years

    How do I get stack traces in Perl?

    • nurp
      nurp almost 6 years
      perl -d script.pl DB<1> t 50 Trace = on (to level 51) DB<2> T
  • ysth
    ysth about 14 years
    That sends the stack trace and error to STDERR; if you need to capture it, directly use the underlying Carp::longmess(). And Carp::cluck is like confess but dies afterwards.
  • mob
    mob about 14 years
    I think that's backwards -- cluck is a warn with a stack trace and confess is a die.
  • jrockway
    jrockway about 14 years
    Uh, or use Devel::StackTrace.
  • Robert P
    Robert P about 14 years
    That's a fine, other option. But it requires an external module, which a may or may not find appealing. Why not just post that as an answer, instead of downvoting?
  • brianegge
    brianegge almost 11 years
    I seem to need to do -MCarp=verbose
  • x-yuri
    x-yuri almost 5 years
    You can find an example of using caller in this answer.