Question

I am writing a program in which most of the used library functions return -1 on error and set errno. The behaviour of the program is such that it exits if error occurs. To determine exact exit point and the error from outside the program (example using gdb), I want to use following method:

err = func_1(..arglist_1..);
if(err != 0)
{
    perror("func(..arglist..)");
    return ((1u << 8) | errno);
}
//..
//.. some more funcs
//..
err = func_n(..arglist_n..);
if(err != 0)
{
    perror("func(..arglist_n..)");
    return (((unsigned)n << 8) | errno);
}

The problem here is safe assumptions.

Reality: errno is declared as extern int errno; inside errno.h
Assumption 1: Value of errno is always less than 255.
Assumption 2: errno is always positive.

On the basis of all the error constants (EAGAIN, etc) defined in errno.h, these assumptions are true at present. Can these be assumed to be true in future also?

P.S.: I do not want to depend on perror() to determine exit point.

Was it helpful?

Solution

Your program's exit status is limited to 0..255, so if those return statements are from the main() program, the high order bits are irrelevant.

The C standard (ISO/IEC 9899:2011 §7.5 Errors <errno.h>) says:

errno
which expands to a modifiable lvalue201) that has type int and thread local storage duration, the value of which is set to a positive error number by several library functions.

201) The macro errno need not be the identifier of an object. It might expand to a modifiable lvalue resulting from a function call (for example, *errno()).

The C standard expects errors to be positive. POSIX (IEEE Std 1003.1, 2013 Edition) states for <errno.h>:

The <errno.h> header shall define the following macros which shall expand to integer constant expressions with type int, distinct positive values (except as noted below), and which shall be suitable for use in #if preprocessing directives: ...

So, you can reasonably safely assume that (system generated) error numbers are positive, but your code could set errno negative (or zero). At the moment, no POSIX system generates error numbers higher than somewhere under 200, so assuming they will be limited to 255 is safe in the short term but probably not in the long term. There's no reason why they should be so limited.

Your claimed 'reality' only applies to non-threaded programs. If you are compiling for threaded support, then errno is not simply declared as extern int errno; and under no circumstances should you attempt to declare errno for yourself. The only safe way to declare it is via the <errno.h> header.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top