The C standard mandates that no C standard library functions shall set errno
to zero. Why exactly is this?
I could understand it being useful for calling several functions, and only checking errno
after the last one – for example:
errno = 0;
double x = strtod(str1, NULL);
long y = strtol(str2, NULL);
if (errno)
// either "strtod" or "strtol" failed
else
// both succeeded
However, is this not considered "bad practice"? Since you're only checking errno
at the very end, you only know that one of the functions did fail, but not which function failed. Is simply knowing that something failed good enough for most practical programs?
I tried looking for various C Rationale documents, but many of them don't have much detail for <errno.h>
.
Best Answer
The C library does not set
errno
to 0 for historical reasons1. POSIX no longer claims its libraries will not alter the value in case of success, and the new Linux man page forerrno.h
reflects this:The ANSI C Rationale states that the committee felt it was more practical to adopt and standardize the existing practice of using
errno
.There is almost always a way to check for error outside of checking if
errno
got set. Checking iferrno
got set is not always reliable, since some calls require calling a separate API to get the error reason. For instance,ferror()
is used to check for an error if you get a short result fromfread()
orfwrite()
.Interestingly enough, your example of using
strtod()
is one of the cases where settingerrno
to 0 before the call is required to correctly detect if an error has occurred. All thestrto*()
string to number functions have this requirement, because a valid return value is returned even in the face of an error.The above code is based on the behavior of
strtod()
as documented on Linux. The C standard only stipulates that underflow cannot return a value greater than the smallest positivedouble
, and whether or noterrno
is set toERANGE
is implementation defined2.There is actually an extensive cert advisory write-up that recommends always setting
errno
to 0 before a library call and checking its value after the call indicates a failure has occurred. This is because some library calls will seterrno
even if the call itself was successful3.1. Previously I claimed it was to avoid masking an error from an earlier call. I can't find any evidence to support this claim. I also had a bogus
printf()
example.2. Thanks to @chux for pointing this out. Reference is C.11 §7.22.1.3 ¶10.
3. Pointed out by @KeithThompson in a comment.