4

这个节目

use warnings;
use strict;
use feature qw(say);

{
    #use autodie;   # all good when this is uncommented
    no autodie;
}

open my $OLDSTD, '>&', *STDOUT;        #--> line 10 (program fails)
open *STDOUT, '>', 'stdout.out';

say "$$ done";

中止

在 problem_no_autodie.pl 第 10 行调用了未定义的子例程。

重申代码中的注释:如果首先有一个use autodie;语句,那么一切都很好。(一切都很好,只有use autodie;也很好。)奇怪的是,在与no autodie声明相同的范围内,我也没有看到这样的问题。只有超出其范围的代码才会失败!有点反作用域,嗯?

如果这个作用域no autodie使用之后出现的,*STDOUT那么一切都很好。*STDOUT在(范围内)之后进一步使用,no autodie会使程序失败。

文档中提到了一个涉及裸词(我不完全理解)的问题,并且该程序确实失败了STDOUT- 但我将它作为*STDOUT.

所以它似乎*STDOUT被视为用户的子,但我不明白这一点,也不明白范围是如何autodie被击败的。(在某些版本中提到范围泄漏是一个错误,但以一种看似无关的方式。)这存在一个实际问题。

我不在autodie我的代码中使用。但是考虑一下我确实使用的这个子

sub isatty {
    no autodie;
    state $isatty = open(my $tty, '+<', '/dev/tty');
    return $isatty;
}

失败是合法的open,因此我们必须autodie在该范围内禁用,以防子用户打开它。那么所描述的行为会受到伤害吗?在什么情况下?

我对这种效果no autodie和它超出其范围的泄漏以及它们所有奇怪的细节感到困惑。但真正令人担忧的是,我不确定如何保护使用上述库的代码免受这种行为的影响,因为我不理解它。有任何想法吗?

我在 CentOS 7.8 上的 5.16.3(系统)、5.26.2 和 5.30.0(perlbrew)下看到了这个

我在 5.32.0 上看不到这种行为那里没有失败。


与的... or die $!检查open没有任何区别,因此为简单起见未显示。

4

1 回答 1

2

此错误在 autodie 2.24 中引入,并在 autodie 2.30 中修复。

$ ( cd ./autodie-2.23; perl Makefile.PL >&3; make >&3; perl -Mblib ../a.pl && echo ok ) 3>/dev/null
ok

$ ( cd ./autodie-2.24; perl Makefile.PL >&3; make >&3; perl -Mblib ../a.pl && echo ok ) 3>/dev/null
Undefined subroutine called at ../a.pl line 10.

$ ( cd ./autodie-2.29; perl Makefile.PL >&3; make >&3; perl -Mblib ../a.pl && echo ok ) 3>/dev/null
Undefined subroutine called at ../a.pl line 10.

$ ( cd ./autodie-2.30; perl Makefile.PL >&3; make >&3; perl -Mblib ../a.pl && echo ok ) 3>/dev/null
ok

$ ( cd ./autodie-2.31; perl Makefile.PL >&3; make >&3; perl -Mblib ../a.pl && echo ok ) 3>/dev/null
ok

(在 CPAN 上找不到 2.30。)

要防止出现此问题,请添加对 autodie 2.30 或更高版本的依赖项。

于 2020-09-28T16:09:53.143 回答