2
perl -wle 'if (0) {no_such_func()}'

尽管使用了 -w,但上述运行没有错误,因为 no_such_func() 从未被调用。

如何让 Perl 检查我引用的所有函数/模块,即使是我不使用的?

在更现实的情况下,某些函数可能只在特殊情况下调用,但我仍然想确保它们存在。

编辑:我安装了 perlcritic,但我认为我仍然做错了什么。我创建了这个文件:

#!/bin/perl -w   
use strict; 
if (0) {no_such_func();}

并且 perlcritic 说这很好(“来源 OK”)。静态分析肯定可以捕捉到 no_such_func() 的不存在吗?该程序也运行良好(并且不产生任何输出)。

4

3 回答 3

7

你不能这样做,因为 Perl 直到运行时才知道函数是否存在。它不能。考虑一个只被eval编辑存在的函数:

eval 'sub foo { return $_[0]+1 }';

那行代码将在运行时创建一个子例程。

或者考虑一下 Perl 可以使用符号引用

my $func = 'func';
$func = "no_such_" . $func;
&$func;

在这种情况下,它正在调用您的no_such_func函数,但您无法通过静态分析来判断。

顺便说一句,如果你想找到从未引用过的函数,至少通过静态分析,那么你可以使用像 Perl::Critic 这样的工具。请参阅http://perlcritic.com/或从 CPAN 安装 Perl::Critic。

于 2013-10-26T21:49:43.923 回答
1

嗯,这很困难:当 Perl 解析函数调用时,它并不总是知道该函数是否存在。这是在声明函数之前调用函数的情况:

foo();
sub foo { say 42 }

有时,该功能可能仅在运行时可用:

my $bar = sub { say 42 };
my $baz = sub { say "" };
*foo = rand > 0.5 ? $bar : $baz;
foo();

(此时我想提一下“只有 perl 可以解析 Perl”这个梗。)

我敢肯定,当函数在运行时之前无法解析时,你可以破解 perl 内部来抱怨,但考虑到上面的用例,这并不是很有用。

于 2013-10-26T21:46:01.213 回答
0

如果您调用所有不带括号的子程序,您可以强制编译时检查。所以以下将失败:

$ perl -e 'use strict; my $condvar; if ($condvar) {no_such_func}'                     
Bareword "no_such_func" not allowed while "strict subs" in use at -e line 1.
Execution of -e aborted due to compilation errors.

(但是,如果您编写它并不会失败if (0),似乎 perl 的优化器正在删除整个块而没有进一步检查)

这导致您必须在使用它们之前定义所有子例程。如果你像这样工作,那么有时“前向”声明是必要的。但是,前向声明可能永远不会得到定义,这是另一种可能的错误情况。

于 2013-10-27T22:49:20.250 回答