The documentation largely tells you which function can set which values in errno
, but there are some rules you need to know:
- No library function sets
errno
to zero. - It is only valid to test
errno
when the function has indicated that an error has occurred (and the function is documented to seterrno
).
The first point means that if you want to know whether, for example, you've gotten an error from strtol()
, you have to set errno
to 0 before calling it.
The second point is crucial; for example, on Solaris, after many I/O operations when the channel was not a terminal, the setting of errno
would be ENOTTY
(not a terminal). There wasn't an error; nothing had failed; but basing your subsequent actions on errno
alone (and not on the status reported by the I/O operation) would lead you to think everything failed.
Thus, in your code, the fopen()
call may leave errno
as a non-zero value, even though it successfully creates the file stream. You have to use:
const char filename[] = "D:\\crypt.txt";
if ((pFile = fopen(filename, "r")) == 0)
{
fprintf(stderr, "Failed to open %s for reading (%d: %s)\n",
filename, errno, strerror(errno));
...return or exit...
}
Beware: if you need to call a function that can alter errno
, capture the value early:
int errnum = errno;
fprintf(stderr, "Failed to open %s for reading (%d: %s)\n",
filename, errnum, strerror(errnum));
And never declare errno
yourself; always use #include <errno.h>
to do it.
I'm not clear why your code is not getting an error on the fputc()
call. On my Mac OS X 10.8.3 system, the equivalent code fails with errno
set to 9 (EBADF) 'Bad file descriptor'.
Where is this documented? It's in the C standard, and reinforced by the POSIX standard.
ISO/IEC 9899:2011 §7.5 Errors <errno.h>
¶3 The value of
errno
in the initial thread is zero at program startup (the initial value oferrno
in other threads is an indeterminate value), but is never set to zero by any library function.202) The value oferrno
may be set to nonzero by a library function call whether or not there is an error, provided the use oferrno
is not documented in the description of the function in this International Standard.202) Thus, a program that uses
errno
for error checking should set it to zero before a library function call, then inspect it before a subsequent library function call. Of course, a library function can save the value oferrno
on entry and then set it to zero, as long as the original value is restored iferrno
’s value is still zero just before the return.
The wording in previous versions of the C standard did not mention threads but was otherwise similar.
Note that the description of fopen()
in the C standard does not mention errno
. Therefore, it is permitted to set errno
by the C standard. By contrast, the mbsrtowcs()
function is documented to set errno
to EILSEQ; it probably can't set it to other values because the C standard says it shouldn't (though there's nothing much to stop an implementation from doing so if it has a better error for some condition).
POSIX 2008
The POSIX page for errno
says:
Many functions provide an error number in
errno
, which has typeint
and is defined in<errno.h>
. The value oferrno
shall be defined only after a call to a function for which it is explicitly stated to be set and until it is changed by the next function call or if the application assigns it a value. The value oferrno
should only be examined when it is indicated to be valid by a function's return value. Applications shall obtain the definition oferrno
by the inclusion of<errno.h>
. No function in this volume of POSIX.1-2008 shall seterrno
to 0. The setting oferrno
after a successful call to a function is unspecified unless the description of that function specifies thaterrno
shall not be modified.It is unspecified whether
errno
is a macro or an identifier declared with external linkage. If a macro definition is suppressed in order to access an actual object, or a program defines an identifier with the nameerrno
, the behavior is undefined.The symbolic values stored in errno are documented in the ERRORS sections on all relevant pages.
The wording in previous versions was similar.