7

在挖掘一些旧的源代码时,我看到了以下内容:

my $module = $some{module};
eval "require $module";
die "Bad module\n$@" if $@;

虽然我了解代码的作用,但它会尝试“要求”一个模块并在它不成功时死掉 - 批评者抱怨它

“eval”的表达形式在第 331 行第 13 列。参见 PBP 的第 161 页。(严重性:5)

不幸的是我没有PBP书,所以想知道上面的正确方法是什么......

此外,在同一来源中发现:

sub test_repo_file {
    my($self, $repo, $test) = @_;
    my $abspath = repo_abs_path($repo);
    return "eval -$test $abspath";
}

这里不明白是什么解决了“eval”,perlcritic 再次抱怨“string eval”......

有人可以解释一下关于“字符串评估”的基本要点以及如何正确编写上述内容吗?

4

2 回答 2

8

跑步perlcritic --verbose '%d\n'也会给你解释:

`eval' 的字符串形式每次执行时都会重新编译,而块形式只编译一次。此外,字符串形式不会给出编译时警告。

   eval "print $foo";        # not ok
   eval {print $foo};        # ok

适用于第一种情况。

第二种情况不会为我生成任何消息。岂不是更

return eval "-$test $abspath"

你不能在这里使用块评估。您应该验证 $test 确实包含它应该包含的内容

$test =~ /^[a-z]$/i

并避免评估 $abspath:

eval "-$test \$abspath"

如果您对此感到满意,则可以添加

## no critic

到行尾。

于 2015-04-15T22:29:04.120 回答
5

很少有用户必须使用eval EXPR. 大多数时候,它在不应该使用的时候(例如)被用作模板系统s/.../eval($repl)/e,或者在应该使用时用于捕获异常eval BLOCK

如果有使用它的理由,那就是执行生成的代码或用户提交的代码。生成代码很棘手且容易出错,并且错误具有安全隐患。执行用户提交的代码是一个主要的安全问题。因此,每次使用eval EXPR都应仔细审查。

perlcritic鉴于几乎每次使用都是具有重大安全隐患的错误,因此标记其使用是非常合适的。


在您的情况下,使用eval EXPR是次优的。我会用

my $path = $module . ".pm";
$path =~ s{::}{/}g;
eval { require $path }

是的,这是便携式的。

于 2015-04-15T22:57:58.267 回答