简体   繁体   English

在stdin,stdout,stderr上捕获错误

[英]Catch errors on stdin, stdout, stderr

I was writing a bit C99 code reading from stdin: 我正在写一些从stdin中读取的C99代码:

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

But I am wondering if I should catch errors in this case, since the shell could redirect stdin to anything that may be less robust than plain stdin . 但是我想知道在这种情况下是否应该捕获错误,因为shell可以将stdin重定向到可能不如普通stdin健壮的任何东西。 But that would also mean, that every access on stdin , stdout and stderr has to be checked for errors, and I seldomly see any checks after printf and co. 但这也意味着,必须检查对stdinstdoutstderr每次访问是否有错误,而且在printf和co之后我很少看到任何检查。

So, is it recommended to check every stream access for errors? 因此,是否建议检查每个流访问是否有错误?

The above example would then be something like: 上面的示例将是这样的:

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

Thanks in advance! 提前致谢!

You always have to check the return value from fgets() , every time you use it. 每次使用它时,您始终必须检查fgets()的返回值。 If you don't, you have no idea whether there is useful data in the buffer; 如果不这样做,则不知道缓冲区中是否有有用的数据。 it could hold the last line a second time. 它可以第二次保持最后一行。 Similar comments apply to every read operation; 类似的注释适用于每个读取操作。 you must check whether the read operation returned what you expected. 您必须检查读取操作是否返回了预期的结果。

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

In the handling code, you need to decide what to do. 在处理代码中,您需要决定要做什么。 You can legitimately use feof() and ferror() in that code. 您可以在该代码中合法使用feof()ferror() The correct reaction to the problem depends on your code. 对问题的正确反应取决于您的代码。 Detecting EOF is usually a cause for exiting the loop or exiting the function ( break or return , but you only return if the function did not open the file; otherwise you have to close the file at least). 检测EOF通常是退出循环或退出函数的原因( breakreturn ,但是只有在函数未打开文件的情况下才返回;否则,至少必须关闭文件)。 Detecting errors on stdin is going to be a rare occurrence; stdin上检测错误将很少见。 you will have to decide what's appropriate to do. 您将必须决定适合做些什么。

Detecting errors on write to stderr or stdout is something that's less often done, but it is arguably sloppy programming to omit them. 检测写到stderrstdout stderr不是很常见,但是可以忽略掉它们是很松懈的编程。 One issue, especially if it is stderr that has the problem, is "how are you going to report the error?" 一个问题(尤其是如果stderr出了问题)是“您将如何报告该错误?” You might need to use syslog() instead, but that's the sort of issue you have to think about. 您可能需要改用syslog() ,但这是您必须考虑的问题。

It depends on the nature of the application you are developing. 这取决于您正在开发的应用程序的性质。 For example if you are developing a hard real time system whose abnormal termination results in severe problems. 例如,如果您正在开发硬实时系统,其异常终止会导致严重问题。 then you should take precaution to deal with all kinds of data streaming errors. 那么您应该采取预防措施来处理各种数据流错误。 On such situations use the following code, 在这种情况下,请使用以下代码,

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

or some construct similar to it. 或类似的结构。 But if your application's rare failures won't have any severe consequences you don't need to check every data streaming operation. 但是,如果应用程序的罕见故障不会造成任何严重后果,则无需检查每个数据流操作。

Here's a fun exercise. 这是一个有趣的练习。 Find someone's interactive program, run it until it asks for input from the terminal, and press control-D (EOF). 找到某人的交互式程序,运行该程序,直到从终端要求输入,然后按Control-D(EOF)。 Odds are that the author doesn't check feof(stdin) and his gets() calls keep just returning 0 bytes which the code interprets as a blank line. 可能是作者没有检查feof(stdin),而他的gets()调用仅返回0字节,该代码将其解释为空白行。 If it takes that as invalid input and re-prompts, it'll end up in an infinite loop! 如果将其视为无效输入并再次提示,则将陷入无限循环!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM