2015-11-29 1 views
0

Je vérifie le code source pour errno.h ici: http://unix.superglobalmegacorp.com/Net2/newsrc/sys/errno.h.htmlOù errno est défini et attribué en C/C++?

Il montre que errno est déclarée comme extern, et quand nous utilisons errno nous pouvons attribuer une valeur directement. Cela signifie que errno est défini et attribué ailleurs, où est défini en effet?

+0

'errno' doit seulement se comporter comme un «int» global. Il n'a pas besoin d'être défini en tant que tel, en général c'est une macro qui retourne une lvalue, comme '#define errno (* (int *) getErrnoPtr())' ou quelque chose. Pourquoi vous souciez-vous de la définition spécifique? – mtijanic

+0

La même réponse que: 'printf' est déclaré (implicitement comme extern), et nous pouvons l'appeler, alors où est-il défini? – immibis

+0

Il est probablement affecté, comme dans le stockage réel, dans l'en-tête de la pile de threads. Son 'emplacement' est OS/architecture défini et, puisqu'il doit être spécifique au thread, l'en-tête de la pile semble être l'endroit évident pour le système d'exploitation pour le mettre. –

Répondre

5

Dans l'exemple lié au code source avec un copyright datant de plus de 20 ans, la bibliothèque d'exécution C a probablement une variable int errno; quelque part. extern int errno; dans un en-tête signifie simplement "cette variable existe, vous la trouverez ailleurs" - peut-être à côté du code qui appelle réellement votre main, ou quelque chose de similaire.

Typiquement dans un système d'exploitation moderne avec des threads, errno n'est pas strictement une variable.

Ceci est l'exemple sous Linux, à partir de /usr/include/bits/errno.h dans la glibc.

# ifndef __ASSEMBLER__ 

/* Function to get address of global `errno' variable. */ 
extern int *__errno_location (void) __THROW __attribute__ ((__const__)); 

# if !defined _LIBC || defined _LIBC_REENTRANT 
/* When using threads, errno is a per-thread value. */ 
# define errno (*__errno_location()) 
# endif 
# endif /* !__ASSEMBLER__ */ 
#endif /* _ERRNO_H */ 

Exactement comment cela le __errno_location est mis en œuvre dépend de la version de ce système d'exploitation, mais essentiellement, il y a quelque chose comme:

__thread int errno; 

__thread se traduit par le spécificateur de stockage C++ 11 thread_local, et est pris en charge par le système d'exploitation comme une sorte de stockage de type «échange de données par thread». Exactement comment cela est mis en œuvre est encore en fonction de l'OS. En x86 et x86-64, fs et gs sont utilisés pour "par CPU" et "par thread" de stockage (mais ils sont "opposés" et je ne me souviens pas très bien lequel est en ce moment)