为啥这个关于 strict subs 的错误只会在 autodie 下触发?

Posted

技术标签:

【中文标题】为啥这个关于 strict subs 的错误只会在 autodie 下触发?【英文标题】:Why does this error about strict subs only trigger under autodie?为什么这个关于 strict subs 的错误只会在 autodie 下触发? 【发布时间】:2020-05-09 04:04:53 【问题描述】:

鉴于这样的代码,我没有收到任何警告。

use strict;
use warnings;
open STDERR, '>&', STDOUT;

鉴于此代码,我得到一个致命错误。

use strict;
use warnings;
use autodie;
open STDERR, '>&', STDOUT;

在 ./test.pl 中使用“strict subs”时不允许使用裸词“STDOUT” 第 6 行。./test.pl 的执行由于编译错误而中止。

为什么 autodie 指向严格的 subs 是这个错误的根源 - 当在第一个示例中明确启用严格并且我没有错误时。

diagnostics 错误解释如下..

./test.pl 第 7 行使用“strict subs”时不允许使用裸词“STDOUT”。 ./test.pl 的执行因编译错误而中止 (#1) (F) 使用“strict subs”时,只允许在大括号中或“=>”左侧使用裸字作为子例程标识符象征。也许你需要预先声明一个子程序?

这一切都可以通过做来解决

open STDERR, '>&', *STDOUT;

那么它不是一个bareword,但是为什么bareword 是open without autodie 而不是autodie 的特殊大小写?这里发生了其他事情吗?

【问题讨论】:

因为 autodie 用一个没有相同 parser 特殊情况的常规 Perl 函数替换了内置函数。 这是反对使用autodie 的理由之一。它有人们意想不到的边缘情况。在许多情况下,我认为这种折衷是不值得的,尤其是当我想向用户提供有用的错误消息而不是向程序员提供技术详细信息时。 【参考方案1】:

autodie 通过导出一个名为 open 的 sub 来完成它的任务,Perl 使用它来支持 open 运算符。

$ perl -MO=Concise,-exec -e'             open(my $fh, "<", "foo")'
...
8  <@> open[t3] vK/3
...

$ perl -MO=Concise,-exec -e'use autodie; open(my $fh, "<", "foo")'
...
7  <#> gv[*open] s
8  <1> entersub vKS
...

open 运算符有特殊的解析规则,原型无法复制[1],因此 open 运算符无法被 sub 准确复制。这解释了观察到的差异。


    通常,prototype("CORE::opname") 会为此类运算符返回 undefined,但 prototype("CORE::open") 会错误地报告 open 的解析规则等同于 *;$@ 原型。

【讨论】:

这是因为常规函数不能接受裸词吗?但是他们可以接受类型球吗?如果是这样,如果您想将其添加到您的第一句话中,我会将其标记为已接受。否则我不确定我是否在关注并想知道为什么open 很特别(或者如果STDOUT 很特别。STDOUT 总是更合适*STDOUT 他们不同吗? 在有问题的用法中,open 接受一个裸词,因为前面的参数是 &gt;&amp;。如果是第二个参数&gt;,则不会接受裸词(在use strict 下)。这种条件行为不能被原型复制。

以上是关于为啥这个关于 strict subs 的错误只会在 autodie 下触发?的主要内容,如果未能解决你的问题,请参考以下文章

为啥按钮只会在手动更改输入后更改对象属性?

为啥 JSLint 会在这个函数上给出严格的违规错误?

为啥受保护的构造函数会在此代码中引发错误?

为啥这个程序会在 C 中给出 Invalid memory access 错误? [关闭]

为啥这个使用字符串连接的查询会在 SQL Server Compact Edition 中引发错误?

为啥 Redis 具有 Pub/Sub 功能?