尝试打印到已关闭的文件句柄没有错误或警告

mak*_*mak 7 perl warnings filehandle

在下面的小代码中,我没有收到行 [09] 和 [18] 的错误或警告。我得到的唯一警告是第 [21] 行:

use strict;                                              # [01]
use warnings FATAL => 'unopened';                        # [02]
                                                         # [03]
open(my $outHandleA, ">outputA.txt") or die ("A: $!\n"); # [04] Opened $outHandleA
print $outHandleA "FILE A\n";                            # [05]
close $outHandleA;                                       # [06] Closed $outHandleA
                                                         # [07]
print $outHandleA;                                       # [08]
print $outHandleA "ABC\n";                               # [09] <---
print $outHandleA;                                       # [10]
print "-----";                                           # [11]
                                                         # [12]
open(OUT, ">outputB.txt") or die ("B: $!\n");            # [13] Opened OUT
print OUT "FILE B\n";                                    # [14]
close OUT;                                               # [15] Closed OUT
                                                         # [16]
print OUT;                                               # [17]
print OUT "DEF\n";                                       # [18] <---
print OUT;                                               # [19]
                                                         # [20]
print DOES_NOT_EXIST_HANDLE "GHI\n";                     # [21] Raises a FATAL warning
                                                         # [22]
print "JKL";                                             # [23] Does not reach here (as expected)
Run Code Online (Sandbox Code Playgroud)

但是,行 [09] 和 [18] 是否也应该引发错误或警告,因为它已关闭(未打开),如下所示?

  • 错误: print() on closed filehandle $outHandleA at printingToClosedHandle.pl line 9.
  • 警告: print() on unopened filehandle $outHandleA at printingToClosedHandle.pl line 9.

这可能是我的 Perl 版本的问题,它是“为 MSWin32-x64-multi-thread 构建的 perl 5, version 28, subversion 1 (v5.28.1)”。此外,这是我在下面得到的程序的输出:

输出A.txt 输出B.txt 标准输出
文件A 文件乙 全局(0xfeb428)全局(0xfeb428)-----

上表中的 STDOUT 输出来自行 [08]、[10] 和 [11]。请注意,上表中括号 (...) 之间的值可能会随着每次执行而改变。

zdi*_*dim 5

已打开(初始化)并关闭的文件句柄与根本未打开的文件句柄之间存在差异;尝试向他们打印会产生不同的警告。perldiag 中“未打开”条目之一

%s() on unopened %s
(W unopened) 试图对从未初始化的文件句柄进行 I/O 操作。您需要执行 open()、sysopen() 或 socket() 调用,或者从 FileHandle 包中调用构造函数。

关闭文件句柄上的 print()条目说

在关闭的文件句柄 %s 上打印()
(W 关闭)您正在打印的文件句柄在此之前的某个时间自行关闭。检查您的控制流。

不过,他们都收到了警告。

use warnings FATAL => 'unopened'单独启用时,打印到已初始化但随后关闭的文件句柄不会收到警告。

use warnings;
#use warnings FATAL => 'unopened';
use strict;
use feature 'say';

open my $stdout, '>&', *STDOUT;    # a copy

say $stdout "hi";
close $stdout;
say $stdout "to lexical, closed";  # it warns (l.10)

FATAL_warnings_unopened: { 
    no warnings;                   # change to FATAL for 'unopened'
    use warnings FATAL => 'unopened';

    say $stdout "with FATAL to closed fh";      # no warning
    close STDOUT;
    say "with FATAL to STDOUT";                 # no warning

    say NON_EXISTENT_FH "no such filehandle!";  # l.20
};

say STDERR 'done';
Run Code Online (Sandbox Code Playgroud)

这打印

你好
在 warnings_FATAL.pl 第 10 行的关闭文件句柄 $stdout 上 say()。
say() 未打开的文件句柄 NON_EXISTENT_FH 在 warnings_FATAL.pl 第 20 行。

它确实退出,每个 FATAL 和块内的unopened文件句柄NON_EXISTENT_FH,但没有警告打印$stdout在它的正上方。第一个这样的打印有一个警告。STDOUT刚刚关闭的打印也不会收到警告。

如果我们use warnings FATAL...在一开始就取消注释该行(并删除其他warnings行),则根本不会发出打印到关闭句柄的警告。

仔细阅读警告 pragma的文档会很有帮助。简而言之,我建议始终首先拥有use warnings;自己,然后为想要创建的类别添加一个声明FATAL(其中多个类别可以添加到同一个声明中)。