user1678062
user1678062

Reputation: 573

Catch errors on stdin, stdout, stderr

I was writing a bit C99 code reading from stdin:

// [...]
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. 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.

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!

Upvotes: 0

Views: 2936

Answers (3)

Jonathan Leffler
Jonathan Leffler

Reputation: 755026

You always have to check the return value from fgets(), every time you use it. 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. 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). Detecting errors on stdin is going to be a rare occurrence; 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. One issue, especially if it is stderr that has the problem, is "how are you going to report the error?" You might need to use syslog() instead, but that's the sort of issue you have to think about.

Upvotes: 3

DoxyLover
DoxyLover

Reputation: 3484

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). 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. If it takes that as invalid input and re-prompts, it'll end up in an infinite loop!

Upvotes: 0

Deepu
Deepu

Reputation: 7610

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.

Upvotes: 1

Related Questions