What is clearerr used for?
There is at least one real world use case for clearerr
: when you want to mimic tail -f
on a file that is not opened in exclusive mode. That means that another (or many other) process(es) write at the end of a file, and one process repeatedly reads even after having reached the end of file in order to look whether new data has arrived. In that case, could would look like:
for (;;) {
if (NULL == fgets(line, sizeof(line), fd)) {
sleep(n);
clearerr(fd); // reset EOF condition
}
else {
fputs(line, fdout);
}
}
Functions that set the error status of a FILE
(as reported by ferror
) do not clear it even if later called successfully. Likewise if you encounter the end of file while reading, it will not be cleared automatically even if the file later has more data available.
Basically this means that if you are using ferror
to check for an error state and you have some way of recovering from it, the ferror
will keep indicating an error until you use clearerr
.
In your example, if you just use the return value of fread
as the condition for terminating the read (i.e., EOF and any type of error are considered final), there is no need to clearerr
: just fall through to fclose
(and perhaps use ferror
to determine whether to print an error message).
On the other hand, if the FILE
is in fact a stream on which read can later succeed, and you detect (or assume) that specific condition and retry, you should clearerr
before retrying or you will keep seeing the old error condition on future attempts.
Likewise, as pointed out in comments, clearerr
also clears the end of file state, so this also applies when using feof
to check for the end of file. (Note, however, that you generally shouldn't use !feof(file)
as the loop condition when reading.)
clearerr()
clears the error and EOF flags from a stream.
Say FILE
were like this:
typedef struct {
int fd;
char *buf;
int error;
int eof;
} FILE;
FILE *file;
This would set file->error
and file->eof
to 0
.
Some reasons for doing this include file I/O, such as when a file gives EOF, but then another program (or another thread, etc.) appends to it. If you clear the error after doing this, you can have your program act as sort of a tail -f
-substitute.