I'm trying to understand how glibc initializes errno
without the preprocessor substituting the errno
symbol.
I first tried to implement a simple version myself based on csu/errno-loc.c and csu/errno.c :
myerrno.h
#ifndef MYERRNO_H
#define MYERRNO_H
extern int *myerrno_location(void);
#define myerrno (*myerrno_location())
#endif
myerrno.c
#include "myerrno.h"
static int myerrno = 0;
int *myerrno_location(void){
return &myerrno;
}
However, when I try to compile I receive the following error messages:
myerrno.c:3:1: error: function ‘myerrno_location’ is initialized like a variable
myerrno.c:3:12: error: static declaration of ‘myerrno_location’ follows non-static declaration
myerrno.h:4:13: note: previous declaration of ‘myerrno_location’ was here
I can tell that the preprocessor is substituting (*myerrno_location(void))
when it encounters myerrno
on line 3 -- and naturally this is expected behavior.
I don't understand why this isn't a problem for glibc . How do thread-safe implementations of errno
get around this preprocessor substitution issue without renaming the static errno
variable?
Fixing your issue is as easy as changing the name of your static variable.
static int myerrno_variable = 0;
int *myerrno_location(void){
return &myerrno_variable;
}
Notice that your version is still not thread safe since all threads are accessing the same myerrno_variable
. A real implementation would return a thread specific memory location. In GCC, there is an extension that provides the __thread
storage class. C.11 provides its own version of that called thread_local
, but it is only available if thread support is provided by the implementation (which can be checked by looking if __STDC_NO_THREADS__
is defined or not).
static __thread int myerrno_variable_gcc; /* if using GCC */
static thread_local int my_errno_variable_c11; /* if __STD_NO_THREADS__ isn't defined */
On a POSIX system without a thread local feature, an implementation could use pthread_getspecific()
to get a pointer to thread specific data that was allocated for each thread, and set with pthread_setspecific()
. See the manual for more information.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.