質問

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.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top