What is errno really defined as
Arjun Shankar
arjun.is@lostca.se
Wed Oct 29 23:55:00 GMT 2014
> Errno is declared as a function returning pointer to int and it does not
> modify or read any golbal variables.
No it isn't. You're referring to this line:
> /* Function to get address of global `errno' variable. */
> extern int *__errno_location (void) __THROW __attribute__ ((__const__));
This line does not declare errno as a function returning pointer to int.
In fact, this line does not define a symbol named errno at all. It declares
a function named '__errno_location' that takes no arguments and returns
a pointer to an integer.
Next, you referred to this line:
> # define errno (*__errno_location ())
And said:
> What I'm confused by though, is the redefinition of errno as
> (*__errno_location ()), namely, why the extra parentheses, no argument,
> no const attribute, and the return type is * vs int * which,
> though defalting to int, is considered bad programming practice?
No. This isn't a redefinition. This is the only definition of errno in
that file. It defines 'errno' as the value stored at the address returned
by a call to the function '__errno_location ()' (which, of course, as I
mentioned earlier, is the very same function referred to above).
I'll quote your first line again, because it seems to have a question about
how errno is read or written:
> Errno is declared as a function returning pointer to int and it does not
> modify or read any golbal variables.
The way errno is defined actually makes it quite easy to read and write it
from the application.
If you wrote:
errno = 0;
It would translate to:
(* __errno_location ()) = 0;
i.e. get the address of errno, then write 0 at that address.
If you wrote:
e = errno;
It would translate to:
e = (* __errno_location ());
i.e. read the value at the address of errno into the variable 'e'.
This implementation allows each thread to maintain its own copy of errno.
If errno were a single global variable, this wouldn't have been possible.
> In the file /usr/include/errno.h errno is declared as "extern int errno;"
Again no. It is only declared if not already defined as a macro.
The entire declaration with context is:
#ifndef errno
extern int errno;
#endif
But 'errno' is already defined at this point, because just prior to this,
bits/errno.h (the file you talked about first) is already included and
a macro named 'errno' already is defined.
Regarding the rest of it, you might want to look at csu/errno.c and read
about thread local storage (often shortened as 'TLS'):
https://gcc.gnu.org/onlinedocs/gcc-4.2.4/gcc/Thread_002dLocal.html
> Does anybody really know what errno is?
I hope that my explanation has been somewhat useful.
Cheers,
Arjun
More information about the Libc-help
mailing list