tags:

views:

116

answers:

4

Is it safe to call errno multiple times when dealing with the same error. Or is it safer to work with a local copy?

This sample illustrates my question:

// If recvfrom() fails it returns -1 and sets errno to indicate the error.
int res = recvfrom(...);
if (res < 0)
{
    // Risky?
    printf("Error code: %d. Error message: %s\n", errno, strerror(errno));

    // Safer alternative?
    int errorNumber = errno;
    printf("Error code: %d. Error message: %s\n", errorNumber, strerror(errorNumber));
}
+4  A: 

The value of errno 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.

http://www.opengroup.org/onlinepubs/009695399/functions/errno.html

However, even strerror could theoretically count as a function call that can change it (see comment by schot) so you should, theoretically, still go with your save-first form.

Habbie
However, printf may cause a change to errno. The man page at http://linux.die.net/man/3/errno (I believe it's from Linux) warns against using it in printf. This is not a problem for your specific situation, however - the compiler will evaluate `errno` and `strerror(errno)` both before calling printf.
Habbie
But the call to `strerror` might change `errno`. Although I don't think there is any implementation stupid/evil enough to do this. (Except maybe a DeathStation 9000).
schot
True, and the compiler might decide to evaluate strerror(errno) before evaluating errno. I'm updating my answer.
Habbie
Unbelievably, `strerror` is specified to write to `errno` under certain conditions: http://www.opengroup.org/onlinepubs/9699919799/functions/strerror.html And ironically, the only way to test if `strerror` failed is by setting `errno` to 0 before calling `strerror`, since the return value does not reflect success or failure. So OP may be onto something...
R..
As far as I know, the C standard allows any library function to update `errno` in completely unspecified ways unless that function is explicitly specified not to, so the issue is even more relevant if we're not talking POSIX.
R..
@R..: according to the link you supplied, strerror can only fail (and thus write to errno) if the supplied error number is not a valid error number.
JeremyP
+1  A: 

errno is variable and not function. Whan you use it, it cannot be reset. So, it is OK to use errno number of times, assuming that you don't call any function that can change/reset errno.

Alex Farber
@Alex: `errno` is not a variable.
Jens Gustedt
+2  A: 

Any standard library function including printf and strerror is allowed to change errno, even if actually no error occurs:

7.5 3 The value of errno is zero at program startup, but is never set to zero by any library function. 170) The value of errno may be set to nonzero by a library function call whether or not there is an error, provided the use of errno is not documented in the description of the function in this International Standard.

Secure
Tangentially related: can you find any language in the standard that would prohibit `strtol` and family from setting `errno` to `ERANGE` when no overflow actually occurred? Standard procedure is to set `errno` to 0 before calling these functions, and check `errno` if `LONG_MIN` or `LONG_MAX` is returned - but if they could set `errno` to `ERANGE` for no reason at all, this standard test seems invalid...
R..
@R..: If the use of errno is defined for a specific function, then no other behaviour than explicitly stated there is allowed by 7.5: "provided the use of errno is not documented in the description of the function".
Secure
Wow it was right there in your citation and I missed it...
R..
+1  A: 

Generally nowadays errno is something much more complicated than a variable:

... errno which expands to a modifiable lvalue that has type int, the value of which is set to a positive error number by several library functions. 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 name errno, the behavior is undefined.

E.g. in POSIX it is guaranteed to evaluate to something that is specific for the current thread. Thus it might have an access cost that is higher than for a simple variable.

So yes I would go for a local copy if performance is a concern, though I never benched this for real.

Jens Gustedt