3

给定一个函数名称,我想报告调用层次结构“一直到顶部”。

例如,

# ./find.pl functionName
functionName
caller
    caller2
    ...
        callerN

在上面的输出中,我了解到 callerN 是“顶级”函数,它最终调用了“最低级”functionName 函数。

我一直在努力做到这一点,但实施总是有缺陷。它不够可靠,我对此没有信心。

有什么东西可以做到这一点吗?

谢谢

4

3 回答 3

3

NYTProf是一个调试包,允许对函数调用进行非常细粒度的检查。它可以输出到 HTML 以查看详细的(运行时)配置文件。根据您的要求,查看它也可以输出的调用图可能会有所帮助。

示例代码:

#!/usr/bin/perl
use strict;
use warnings;

&say_hi;

sub say_hi {
    print &hello;
}
sub hello {
    return "Hello world!\n";
}

调用:

$ perl -d:NYTProf hello.pl

生成一个nytprof.out在当前目录中调用的文件,它nytprof可以解析:

$ nytprof nytprof.out --open

这将创建一个名为nytprof并自动在分析结果页面上为您打开浏览器的目录。有趣的部分可能是您可以下载的图表(但它们也位于nytprof目录中)。这些调用图按层次组织,可以深入了解程序的哪些部分调用了哪些函数。这个简单程序的调用图如下所示:

简单的 hello world 程序的调用图

PS:图表以点文件的形式提供。要创建一个 SVG graph.dot,比如说

$ dot -Tsvg -o graph.svg graph.dot

更多在dot手册中。

于 2012-12-19T10:16:47.147 回答
1

你可以use Carp和它的cluck函数,它打印调用堆栈。有关更多信息,请参阅他们的文档

use strict;
use warnings;

use Carp qw(cluck);

⫕

sub callstack {
    cluck "waaah";
}

sub subsub {
    &callstack;
}

输出:

$ perl /tmp/test.pl
waaah at /tmp/test.pl line 10
    main::callstack called at /tmp/test.pl line 14
    main::subsub called at /tmp/test.pl line 7
于 2012-12-18T11:43:25.870 回答
1

如果实际运行代码可行,可以使用 caller() 函数,或者封装版本的Devel::Stacktrace

如果您依赖代码分析... Lscharf 的 PPI 和 GraphViz 的组合可能会有用。但是,不知道它是否是最新的,或者它是否捕获了无数边缘情况中的任何一种,例如上面 ikegami 提到的。

于 2012-12-18T09:55:30.000 回答