【问题标题】:Catch errors on stdin, stdout, stderr在标准输入、标准输出、标准错误上捕获错误
【发布时间】:2013-05-11 19:44:43
【问题描述】:

我正在写一些从标准输入读取的 C99 代码:

// [...]
fgets(buf, sizeof(buf), stdin);
// [...]

但我想知道在这种情况下是否应该捕获错误,因为 shell 可以将 stdin 重定向到任何可能不如普通 stdin 健壮的东西。但这也意味着,stdin、stdout 和 stderr 上的每次访问都必须检查错误,而我很少看到在 printf 和 co 之后的任何检查。

那么,是否建议检查每个流访问是否有错误?

上面的例子会是这样的:

// [...]
if (!fgets(buf, sizeof(buf), stdin) && ferror(stdin)) {
    exit(EXIT_FAILURE);
}
// [...]

提前致谢!

【问题讨论】:

    标签: c stream stdout stdin stderr


    【解决方案1】:

    这取决于您正在开发的应用程序的性质。例如,如果您正在开发一个硬实时系统,其异常终止会导致严重问题。那么您应该采取预防措施来处理各种数据流错误。在这种情况下使用以下代码,

    if (!fgets(buf, sizeof(buf), stdin) && ferror(stdin)) {
        exit(EXIT_FAILURE);
    }
    

    或类似的构造。但是,如果您的应用程序的罕见故障不会产生任何严重后果,则您无需检查每个数据流操作。

    【讨论】:

      【解决方案2】:

      每次使用它时,您总是必须检查来自fgets() 的返回值。如果没有,你就不知道缓冲区中是否有有用的数据;它可以第二次保持最后一行。类似的 cmets 适用于每个读取操作;您必须检查读取操作是否返回了您的预期。

      if (fgets(buf, sizeof(buf), stdin) == 0)
          ...EOF, or some error...
      

      在处理代码中,您需要决定要做什么。您可以在该代码中合法地使用feof() 和ferror()。对问题的正确反应取决于您的代码。检测到 EOF 通常是退出循环或退出函数的原因(break 或 return,但只有在函数没有打开文件时才返回;否则至少必须关闭文件)。在stdin 上检测错误将很少见;你必须决定什么是合适的。

      在写入stderr 或stdout 时检测错误是很少发生的事情,但忽略它们可以说是草率的编程。一个问题,特别是如果是stderr 有问题,是“你将如何报告错误?”您可能需要改用syslog(),但这是您必须考虑的问题。

      【讨论】:

      • 谢谢,我以前从未听说过 syslog。很高兴知道。但是关于 EOF:有时,我有一个预初始化的缓冲区并且不在乎它是否没有更改,但是你是对的,我应该始终关心返回值。
      【解决方案3】:

      这是一个有趣的练习。找到某人的交互式程序,运行它直到它要求终端输入,然后按 control-D (EOF)。奇怪的是作者没有检查 feof(stdin) 并且他的 gets() 调用只返回 0 字节,代码将其解释为空行。如果它把它当作无效输入并重新提示,它将最终陷入无限循环!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-07-21
        • 1970-01-01
        • 1970-01-01
        • 2014-07-22
        • 1970-01-01
        • 1970-01-01
        • 2018-11-25
        • 1970-01-01
        相关资源
        最近更新 更多