1

我试图了解glibcerrno如何在没有预处理器替换errno符号的情况下进行初始化。

我首先尝试基于csu/errno-loc.ccsu/errno.c自己实现一个简单的版本:

迈尔诺

#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;
}

但是,当我尝试编译时,我收到以下错误消息:

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

我可以说预处理器在第 3 行(*myerrno_location(void))遇到时正在替换myerrno——这自然是预期的行为。

我不明白为什么这对glibc来说不是问题。如何在不重命名静态变量errno的情况下解决这个预处理器替换问题的线程安全实现?errno

4

1 回答 1

3

解决问题就像更改静态变量的名称一样简单。

static int myerrno_variable = 0;

int *myerrno_location(void){
    return &myerrno_variable;
}

请注意,您的版本仍然不是线程安全的,因为所有线程都在访问相同的myerrno_variable. 一个真正的实现会返回一个线程特定的内存位置。在 GCC 中,有一个提供__thread存储类的扩展。C.11 提供了自己的调用版本thread_local,但它仅在实现提供线程支持时可用(可以通过查看是否__STDC_NO_THREADS__已定义来检查)。

static __thread int myerrno_variable_gcc;      /* if using GCC */
static thread_local int my_errno_variable_c11; /* if __STD_NO_THREADS__ isn't defined */

在没有线程本地功能的 POSIX 系统上,实现可以pthread_getspecific()用来获取指向为每个线程分配的线程特定数据的指针,并使用pthread_setspecific(). 有关详细信息,请参阅手册

于 2013-08-02T21:10:35.923 回答