在范围“no autodie”之后,程序在“*STDOUT”处终止

2024-03-08

这个节目

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";

中止与



Undefined subroutine called at problem_no_autodie.pl line 10.
  

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

如果这个范围no autodie comes after指某东西的用途*STDOUT然后一切又好了。进一步利用*STDOUT,之后(范围)no autodie,程序失败。

有一个Gotcha https://perldoc.perl.org/autodie.html#GOTCHAS在涉及裸字的文档中提到(我不完全理解),并且该程序确实失败了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)下看到了这个

I do not在 5.32.0 上看到此行为;那里没有失败。


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


This bug https://github.com/pjf/autodie/issues/69在 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 或更高版本的依赖项。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在范围“no autodie”之后,程序在“*STDOUT”处终止 的相关文章

随机推荐