3 回答

TA貢獻(xiàn)1836條經(jīng)驗(yàn) 獲得超13個(gè)贊
是
Errno不再是一個(gè)簡(jiǎn)單的變量,它是幕后復(fù)雜的事情,特別是它具有線程安全性。
見(jiàn)$ man 3 errno:
ERRNO(3) Linux Programmer’s Manual ERRNO(3)
NAME
errno - number of last error
SYNOPSIS
#include <errno.h>
DESCRIPTION
...
errno is defined by the ISO C standard to be a modifiable lvalue of
type int, and must not be explicitly declared; errno may be a macro.
errno is thread-local; setting it in one thread does not affect its
value in any other thread.
我們可以仔細(xì)檢查:
$ cat > test.c
#include <errno.h>
f() { g(errno); }
$ cc -E test.c | grep ^f
f() { g((*__errno_location ())); }
$

TA貢獻(xiàn)1856條經(jīng)驗(yàn) 獲得超17個(gè)贊
在errno.h中,此變量聲明為extern int errno;
這是C標(biāo)準(zhǔn)所說(shuō)的:
宏errno不必是對(duì)象的標(biāo)識(shí)符。它可能會(huì)擴(kuò)展為由函數(shù)調(diào)用(例如*errno())產(chǎn)生的可修改的左值。
通常,errno是一個(gè)宏,它調(diào)用一個(gè)函數(shù),該函數(shù)返回當(dāng)前線程的錯(cuò)誤號(hào)的地址,然后將其取消引用。
這是我在Linux上的/usr/include/bits/errno.h:
/* 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
最后,它將生成這種代碼:
> cat essai.c
#include <errno.h>
int
main(void)
{
errno = 0;
return 0;
}
> gcc -c -Wall -Wextra -pedantic essai.c
> objdump -d -M intel essai.o
essai.o: file format elf32-i386
Disassembly of section .text:
00000000 <main>:
0: 55 push ebp
1: 89 e5 mov ebp,esp
3: 83 e4 f0 and esp,0xfffffff0
6: e8 fc ff ff ff call 7 <main+0x7> ; get address of errno in EAX
b: c7 00 00 00 00 00 mov DWORD PTR [eax],0x0 ; store 0 in errno
11: b8 00 00 00 00 mov eax,0x0
16: 89 ec mov esp,ebp
18: 5d pop ebp
19: c3 ret
添加回答
舉報(bào)