【问题标题】:Is close/fclose on stdin guaranteed to be correct?标准输入上的 close/fclose 是否保证正确?
【发布时间】:2008-11-13 20:00:13
【问题描述】:

似乎以下调用符合您的预期(关闭流并且不允许任何进一步的输入 - 任何等待流上输入的东西都会返回错误),但它是否保证在所有编译器/平台上都是正确的?

close(fileno(stdin));
fclose(stdin);

【问题讨论】:

  • 你可以只使用 fclose(stdin),它会在文件句柄上调用 close()。

标签: c stdio


【解决方案1】:

fclose(stdin) 会导致进一步使用stdin(隐式或显式)来调用未定义的行为,这是非常糟糕的事情。它不会“禁止输入”。

close(fileno(stdin)) 导致任何进一步尝试从stdin 输入,在当前缓冲区已耗尽后,以EBADF 失败,但仅在您打开另一个文件之前,在这种情况下,该文件将变为 fd #0 坏事会发生

更稳健的方法可能是:

int fd = open("/dev/null", O_WRONLY);
dup2(fd, 0);
close(fd);

添加了一些错误检查。这将确保所有读取(在当前缓冲区耗尽后)都会导致错误。如果您只是希望它们导致 EOF,而不是错误,请使用 O_RDONLY 而不是 O_WRONLY

【讨论】:

  • 很遗憾,您的解决方案不可移植,不符合 C99。
  • @nowox:它超出了基本 C 语言的范围,它根本没有你做这种事情所需的概念,但绝不禁止将它定义为更严格的规范。
【解决方案2】:

不要关闭 fileno(FILE*)。 FILE 是一个缓冲对象。调查其实施并干预其状态会带来所有其他软件模块上类似不当行为的警告和危险。

别这样。

啊。严重地。讨厌。

【讨论】:

  • 事实上,如果有任何未完成的数据要刷新,在 fclose() 之前执行 close() 可以保证 fclose() 失败。 (在更一般的情况下,可能是 close() 和 fclose() 之间的其他代码,fclose() 可能只是写入错误的文件!)
  • 这...没有...从技术上回答问题。
  • 这样做:OP 代码的行为将是未定义的。他的 fclose 实现不太可能检测到 fd 已关闭。如果他在调用 close 和 fclose 之间发生了其他事情,那么还有另一种令人讨厌的可能性:刚刚关闭了一个文件描述符,下一次调用 open() 最有可能 - 实际上 - 重用该文件描述符。如果你在底层描述符上调用 close,打开另一个具有相同索引的描述符,然后调用 fclose,会发生什么?至少,最后一个 open() 的 fd 肯定会很糟糕。
【解决方案3】:

在所有可能的操作系统上都不能保证正确。但是,调用 fclose(stdin) 将适用于任何 POSIX 兼容的操作系统以及 Windows 操作系统,因此您目前应该使用几乎所有通用的东西。

如上一个答案以及我的评论所述,无需在文件句柄上调用 close。 fclose() 将为您正确关闭所有内容。

【讨论】:

    猜你喜欢
    • 2013-11-03
    • 2019-08-06
    • 2015-09-28
    • 1970-01-01
    • 2012-02-29
    • 1970-01-01
    • 2020-11-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多