【发布时间】:2021-12-15 19:29:40
【问题描述】:
在寻找在我使用的框架中记录所有使用的子例程的可能性时,我发现了这个question。最佳答案使用子例程 DB::DB 记录所有使用的子例程。 这在某种程度上起作用,与 caller() 一起使用,以找出程序采用的路径。 但是我有一个问题,当程序从一个函数返回并进入一个新函数时,一个子程序被第二次“调用”。
/etc/perl/Devel/AllSubs.pm中的我的 DB::DB
package Devel::AllSubs;
use Data::Dumper;
$Data::Dumper::Sortkeys = 1;
my $LastSub = '::';
sub DB::DB {
my ($Package, $Filename, $Line, $Subroutine) = caller(1);
if ($Subroutine ne $LastSub ){
print STDERR Data::Dumper->Dump(
[
$Package,
$Filename,
$Line,
$Subroutine
],
['Package-1', 'Filename-1', 'Line-1', "Subroutine-1"]
);
COUNT:
for ( my $Count = 2; $Count < 30; $Count++ ) {
my ( $NextPackage, $NextFilename, $NextLine, $NextSubroutine ) = caller( $Count );
last COUNT if !$NextLine;
print STDERR Data::Dumper->Dump(
[
$NextPackage,
$NextFilename,
$NextLine,
$NextSubroutine
],
["Package-$Count", "Filename-$Count", "Line-$Count", "Subroutine-$Count",]
);
}
say STDERR "";
$LastSub = $Subroutine;
}
}
1;
我要检查其调用的程序perl -d:AllSubs AllTest.pl
&One();
sub One {
&Two();
}
sub Two {
&Three();
&Six();
}
sub Three {
&Four();
&Five();
}
sub Four {}
sub Five {}
sub Six {}
1;
上面提到的答案声称,每个子程序都会调用 DB::DB,所以我的预期结果是:
# One
# Two
# Three
# Four
# Five
# Six
我得到的是:
# One
# Two
# Three
# Four
# Three
# Five
# Two
# Six
完整的 dumper 输出是:
$Package-1 = undef;
$Filename-1 = undef;
$Line-1 = undef;
$Subroutine-1 = undef;
$Package-1 = 'main';
$Filename-1 = '/opt/frameworks/test/scripts/AllTest.pl';
$Line-1 = 30;
$Subroutine-1 = 'main::One';
$Package-1 = 'main';
$Filename-1 = '/opt/frameworks/test/scripts/AllTest.pl';
$Line-1 = 34;
$Subroutine-1 = 'main::Two';
$Package-2 = 'main';
$Filename-2 = '/opt/frameworks/test/scripts/AllTest.pl';
$Line-2 = 30;
$Subroutine-2 = 'main::One';
$Package-1 = 'main';
$Filename-1 = '/opt/frameworks/test/scripts/AllTest.pl';
$Line-1 = 38;
$Subroutine-1 = 'main::Three';
$Package-2 = 'main';
$Filename-2 = '/opt/frameworks/test/scripts/AllTest.pl';
$Line-2 = 34;
$Subroutine-2 = 'main::Two';
$Package-3 = 'main';
$Filename-3 = '/opt/frameworks/test/scripts/AllTest.pl';
$Line-3 = 30;
$Subroutine-3 = 'main::One';
$Package-1 = 'main';
$Filename-1 = '/opt/frameworks/test/scripts/AllTest.pl';
$Line-1 = 43;
$Subroutine-1 = 'main::Four';
$Package-2 = 'main';
$Filename-2 = '/opt/frameworks/test/scripts/AllTest.pl';
$Line-2 = 38;
$Subroutine-2 = 'main::Three';
$Package-3 = 'main';
$Filename-3 = '/opt/frameworks/test/scripts/AllTest.pl';
$Line-3 = 34;
$Subroutine-3 = 'main::Two';
$Package-4 = 'main';
$Filename-4 = '/opt/frameworks/test/scripts/AllTest.pl';
$Line-4 = 30;
$Subroutine-4 = 'main::One';
$Package-1 = 'main';
$Filename-1 = '/opt/frameworks/test/scripts/AllTest.pl';
$Line-1 = 38;
$Subroutine-1 = 'main::Three';
$Package-2 = 'main';
$Filename-2 = '/opt/frameworks/test/scripts/AllTest.pl';
$Line-2 = 34;
$Subroutine-2 = 'main::Two';
$Package-3 = 'main';
$Filename-3 = '/opt/frameworks/test/scripts/AllTest.pl';
$Line-3 = 30;
$Subroutine-3 = 'main::One';
$Package-1 = 'main';
$Filename-1 = '/opt/frameworks/test/scripts/AllTest.pl';
$Line-1 = 44;
$Subroutine-1 = 'main::Five';
$Package-2 = 'main';
$Filename-2 = '/opt/frameworks/test/scripts/AllTest.pl';
$Line-2 = 38;
$Subroutine-2 = 'main::Three';
$Package-3 = 'main';
$Filename-3 = '/opt/frameworks/test/scripts/AllTest.pl';
$Line-3 = 34;
$Subroutine-3 = 'main::Two';
$Package-4 = 'main';
$Filename-4 = '/opt/frameworks/test/scripts/AllTest.pl';
$Line-4 = 30;
$Subroutine-4 = 'main::One';
$Package-1 = 'main';
$Filename-1 = '/opt/frameworks/test/scripts/AllTest.pl';
$Line-1 = 34;
$Subroutine-1 = 'main::Two';
$Package-2 = 'main';
$Filename-2 = '/opt/frameworks/test/scripts/AllTest.pl';
$Line-2 = 30;
$Subroutine-2 = 'main::One';
$Package-1 = 'main';
$Filename-1 = '/opt/frameworks/test/scripts/AllTest.pl';
$Line-1 = 39;
$Subroutine-1 = 'main::Six';
$Package-2 = 'main';
$Filename-2 = '/opt/frameworks/test/scripts/AllTest.pl';
$Line-2 = 34;
$Subroutine-2 = 'main::Two';
$Package-3 = 'main';
$Filename-3 = '/opt/frameworks/test/scripts/AllTest.pl';
$Line-3 = 30;
$Subroutine-3 = 'main::One';
$Package-1 = undef;
$Filename-1 = undef;
$Line-1 = undef;
$Subroutine-1 = undef;
有没有办法跳过调用 DB::DB 的情况,即使它没有在代码中第二次调用?
编辑:
我取得了一些进展。为每一行代码调用 DB::DB。 DB::sub 另一方面是我需要的。如果我在这里使用 caller(),我会得到 caller(0) 的前一个 sub。当前子在$DB::sub。但我还需要文件名和调用此子的行。它说here $DB::filename 应该包含文件名,但它是空的。我还在这个perl4 book 中找到了一些信息,但目前还不足以帮助我。
【问题讨论】:
-
“这里说 $DB::filename 应该包含文件名,但它是空的” :您可以在源代码here 中找到有关该变量的更多信息