尝试打印到已关闭的文件句柄没有错误或警告 [英] No error or warning for trying to print to an already closed filehandle

查看:26
本文介绍了尝试打印到已关闭的文件句柄没有错误或警告的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

使用严格;# [01]使用警告 FATAL =>'未开封';# [02]# [03]open(my $outHandleA, ">outputA.txt") 或 die ("A: $!\n");# [04] 打开 $outHandleA打印 $outHandleA "文件 A\n";# [05]关闭 $outHandleA;# [06] 关闭 $outHandleA# [07]打印 $outHandleA;# [08]打印 $outHandleA "ABC\n";# [09] <---打印 $outHandleA;# [10]打印-----";# [11]# [12]open(OUT, ">outputB.txt") 或 die ("B: $!\n");# [13] 打开打印出文件 B\n";# [14]关闭;# [15] 关闭# [16]打印;# [17]打印出DEF\n";# [18] <---打印;# [19]# [20]打印 DOES_NOT_EXIST_HANDLE "GHI\n";# [21] 引发致命警告# [22]打印JKL";# [23] 没有到达这里(如预期的那样)

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

  • 错误:print() 在printingToClosedHandle.pl 第9 行的关闭文件句柄$outHandleA 上.
  • 警告:print() 在printingToClosedHandle.pl 第9 行未打开的文件句柄$outHandleA 上.

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

<头>
outputA.txtoutputB.txt标准输出
文件A文件 BGLOB(0xfeb428)GLOB(0xfeb428)-----

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

解决方案

打开(初始化)和关闭的文件句柄和根本没有打开的文件句柄是有区别的;尝试向他们打印会产生不同的警告.perldiag 中的未打开"条目之一

<块引用>

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

while 为 print() 在关闭的文件句柄上的条目

<块引用>

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

他们都收到了警告.

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

使用警告;#使用警告致命=>'未开封';使用严格;使用功能说";打开我的 $stdout, '>&', *STDOUT;# 复印件说 $stdout "hi";关闭 $stdout;说 $stdout to lexical, closed";# 它警告 (l.10)FATAL_warnings_unopened:{没有警告;# 更改为 FATAL 表示 'unopened'使用警告 FATAL =>'未开封';说 $stdout "with FATAL to closed fh";#没有警告关闭标准输出;说对标准输出致命";#没有警告说 NON_EXISTENT_FH没有这样的文件句柄!";# l.20};说 STDERR '完成';

这个打印

<前>你好在 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 行),则不会发出警告以打印到关闭的句柄,完全没有.

仔细阅读 warnings pragma 的文档会很有帮助.简而言之,我建议始终首先让 use warnings; 单独使用,然后为想要制作的类别添加一个声明 FATAL(其中多个类别可能是在同一语句中添加).

In the following small code, I do not get an error or a warning for lines [09] and [18]. The only warning I get is with line [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)

However, shouldn't lines [09] and [18] also raise an error or a warning like the following since it is closed (unopened)?

  • ERROR: print() on closed filehandle $outHandleA at printingToClosedHandle.pl line 9.
  • WARNING: print() on unopened filehandle $outHandleA at printingToClosedHandle.pl line 9.

This might be an issue with my version of Perl which is "perl 5, version 28, subversion 1 (v5.28.1) built for MSWin32-x64-multi-thread". Furthermore, here is the output of the program I get below:

outputA.txt outputB.txt STDOUT
FILE A FILE B GLOB(0xfeb428)GLOB(0xfeb428)-----

The STDOUT output in above table is from lines [08], [10], and [11]. Please note that the value between the parenthesis (...) in the above table might change with each execution.

解决方案

There is a difference between a filehandle that has been opened (initialized) and got closed, and one that has not been opened at all; attempting to print to them draws different warnings. One of 'unopened' entries in perldiag says

%s() on unopened %s
(W unopened) An I/O operation was attempted on a filehandle that was never initialized. You need to do an open(), a sysopen(), or a socket() call, or call a constructor from the FileHandle package.

while an entry for print() on closed filehandle says

print() on closed filehandle %s
(W closed) The filehandle you're printing on got itself closed sometime before now. Check your control flow.

They both get the warnings though.

When use warnings FATAL => 'unopened' alone is enabled then printing to a filehandle that had been initialized but then closed does not get a warning.

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

This prints

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.

It does exit, per FATAL and an unopened filehandle NON_EXISTENT_FH inside the block, but there is no warnings for the print to $stdout right above it. There is a warning for the first such print. A print to STDOUT which just got closed doesn't get a warning either.

If we uncomment the use warnings FATAL... line in the very beginning (and remove other warnings lines) then no warnings are issued for printing to closed handles, at all.

A very close reading of the docs for the warnings pragma is helpful. In short, I'd suggest to always first have use warnings; on its own, and then add a statement for categories wanted to be made FATAL (where multiple categories may be added in the same statement).

这篇关于尝试打印到已关闭的文件句柄没有错误或警告的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆