【问题标题】:How can I monitor the Perl call stack?如何监视 Perl 调用堆栈?
【发布时间】:2011-01-02 18:03:38
【问题描述】:

我在 Windows XP 上使用 ActivePerl 5.8。

use strict;
use warnings;
use Data::Dumper;

我的脚本中使用了三个子例程。

要检测调用堆栈,我只能插入一些print "some location"; 并从控制台窗口检查打印结果。

有什么好的监控方法吗?谢谢。

【问题讨论】:

  • 你为什么要监控调用堆栈?

标签: perl callstack


【解决方案1】:

如果是你的代码,你可能想使用:

Carp::cluck( "And here's the stack:" );

Carp::cluck。它打印出带有堆栈跟踪的警告。它的工作方式类似于调试输出的“printf”样式。

【讨论】:

    【解决方案2】:

    使用调试器的T 命令。

    例子:

    $ perl -d -e'
    sub foo {}
    sub bar { foo; }
    bar;
    '
    
    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::(-e:4):   bar;
      DB<1> s
    main::bar(-e:3):        sub bar { foo; }
      DB<1> s
    main::foo(-e:2):        sub foo {}
      DB<1> T
    . = main::foo() called from -e line 3
    . = main::bar() called from -e line 4
      DB<1> s
    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> q
    

    【讨论】:

      【解决方案3】:

      您没有具体说明为什么要监控调用堆栈并跟踪您的潜艇,因此答案必须广泛。

      一种方法是caller:

      调用者

      返回当前子例程调用的上下文。在标量上下文中,如果有调用者,即如果我们在子例程或 eval 或 require 中,则返回调用者的包名称,否则返回未定义的值。在列表上下文中,返回

      # 0         1          2
      ($package, $filename, $line) = caller;
      

      使用 EXPR,它返回一些额外的信息,调试器用来打印堆栈跟踪。 EXPR 的值表示在当前调用帧之前要返回多少调用帧。

      #  0         1          2      3            4
        ($package, $filename, $line, $subroutine, $hasargs,
      #  5          6          7            8       9         10
      $wantarray, $evaltext, $is_require, $hints, $bitmask, $hinthash)
       = caller($i);
      

      您也可以使用Devel::Cover 模块:

      代码覆盖率数据是使用可插入的 runops 函数收集的,该函数计算每个 op 的执行次数。然后使用 B 编译器模块将这些数据映射回现实。还有一个语句分析工具,需要更好的后端才能真正有用。

      您告诉我们您想做的事情越多,我们的答案对您的帮助就越大!

      【讨论】:

        【解决方案4】:

        您很少需要在 Perl 中直接管理调用堆栈。如果您这样做,caller 就是您想要的工具。但是,它只是很少需要。

        更多时候,我想在调试时查看堆栈跟踪。好消息,它很容易获得堆栈跟踪,只需使用Carpconfesscluck 函数而不是diewarn

        use strict;
        use warnings;
        use Carp;
        
        bar(6.1);
        bar(1);
        
        sub foo {
            confess "Oh noes" unless @_ == 6;  # confess is fatal
        }
        
        sub bar {
            my $count = shift;
            cluck "bar is in trouble" unless int $count == $count;  # cluck is not fatal
            foo( ('a')x $count );
        }
        

        这会让你:

        dao:~ toad$ perl test.pl
        bar is in trouble at test.pl line 14
            main::bar(6.1) called at test.pl line 5
        Oh noes at test.pl line 9
            main::foo('a') called at test.pl line 15
            main::bar(1) called at test.pl line 6
        

        【讨论】:

          猜你喜欢
          • 2012-07-24
          • 1970-01-01
          • 2010-09-18
          • 2014-08-19
          • 1970-01-01
          • 2023-03-11
          • 1970-01-01
          • 2010-10-29
          • 2012-08-26
          相关资源
          最近更新 更多