提问人:mak 提问时间:2/26/2021 最后编辑:zdimmak 更新时间:3/2/2021 访问量:454
尝试打印到已关闭的文件句柄时没有错误或警告
No error or warning for trying to print to an already closed 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)
但是,行 [09] 和 [18] 是否也应该引发错误或警告,如下所示,因为它已关闭(未打开)?
- 错误:
print() on closed filehandle $outHandleA at printingToClosedHandle.pl line 9.
- 警告:
print() on unopened filehandle $outHandleA at printingToClosedHandle.pl line 9.
这可能是我的 Perl 版本的问题,它是“perl 5,版本 28,subversion 1 (v5.28.1) 为 MSWin32-x64-multi-thread 构建”。此外,这是我在下面得到的程序的输出:
输出 .txt | 输出B.txt | 标准输出 |
---|---|---|
文件 A | 文件 B | 格洛布(0xfeb428)格洛布(0xfeb428)----- |
上表中的 STDOUT 输出来自第 [08]、[10] 和 [11] 行。请注意,上表中括号 (...) 之间的值可能会随着每次执行而更改。
答:
已打开(初始化)并关闭的文件句柄与根本没有打开的文件句柄之间存在差异;尝试打印给它们会引出不同的警告。perldiag 中的一个“未开封”条目说
%s() 在未打开的 %s
上(W 未打开) 尝试对从未初始化的文件句柄执行 I/O 操作。您需要执行 open()、sysopen() 或 socket() 调用,或者从 FileHandle 包中调用构造函数。
而关闭的文件句柄上的 print() 条目说
print() on closed filehandle %s
(W closed) 您正在打印的文件句柄在之前的某个时间自行关闭。检查控制流。
不过,他们都收到了警告。
启用单独时,打印到已初始化但随后关闭的文件句柄不会收到警告。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';
这将打印
hi say() on closed filehandle $stdout at warnings_FATAL.pl line 10. say() on unopened filehandle NON_EXISTENT_FH at warnings_FATAL.pl line 20.
根据 FATAL 和块内的文件句柄,它确实退出,但没有警告打印在其正上方。第一次这样的印刷品有一个警告。刚刚关闭的打印件也不会收到警告。unopened
NON_EXISTENT_FH
$stdout
STDOUT
如果我们在一开始就取消注释该行(并删除其他行),则根本不会发出打印到闭合句柄的警告。use warnings FATAL...
warnings
仔细阅读警告编译指示的文档是有帮助的。简而言之,我建议始终首先单独使用,然后为想要制作的类别添加一个声明(可以在同一声明中添加多个类别)。use warnings;
FATAL
评论
use warnings FATAL => 'unopened';
use warnings FATAL => 'closed';
with_FATAL_warnings: { ... };
>&
use warnings;
>&
dup2
man 2 dup
你违反了它的细节和背后的导入机制。也就是说,如果你 ,那么只会被导入,即使正常导出其他东西。use
use Foo 'bar';
Foo::bar
Foo
以同样的方式,不会打开所有警告。它只打开“未打开”警告:use warnings FATAL => 'unopened';
$ perl -E 'use warnings FATAL => "unopened" ; print $x;'
$ perl -E 'use warnings; use warnings FATAL => "unopened" ; print $x;'
Name "main::x" used only once: possible typo at -e line 1.
Use of uninitialized value $x in print at -e line 1.
评论
autodie