本文转载至:http:///2015/03/_gnu_source-vs-__use_gnu/#more-371
c-cpp.c:
| #include <stdio.h> #include <signal.h> //放这里就编译不过 /* get REG_RIP from ucontext.h */ #ifndef __USE_GNU # define __USE_GNU #endif #include <ucontext.h> int main(int argc, char* argv[]) { printf("%dn", REG_R8); return 0; } |
用gcc编译不过,用g++可以: $ g++ c-cpp.c $ gcc c-cpp.c c-cpp.c: In function ‘main’: c-cpp.c:12:17: error: ‘REG_R8’ undeclared (first use in this function) c-cpp.c:12:17: note: each undeclared identifier is reported only once for each function it appears in
其预处理上有差别: $ gcc siginfo.c -E >gcc.c $ g++ siginfo.c -E >g++.c 在/usr/include/x86_64-linux-gnu/sys/ucontext.h 文件里,定义了:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
/*
Container for all general registers. */
typedef
greg_t
gregset_t[NGREG];
#ifdef
__USE_GNU
/*
Number of each register in the `gregset_t' array. */
enum
{
REG_R8
=
0,
#
define REG_R8 REG_R8
REG_R9,
#
define REG_R9 REG_R9
...
#endif
struct
_libc_fpxreg
|
经过预处理,gcc.c显示为:
| typedef greg_t gregset_t[23]; # 94 "/usr/include/x86_64-linux-gnu/sys/ucontext.h" 3 4 struct _libc_fpxreg |
g++.c显示为:
|
typedef
greg_t
gregset_t[23];
enum
{
REG_R8
=
0,
REG_R9,
...
};
struct
_libc_fpxreg
|
很明显,gcc版本的,没有enum,所有gcc编译不过。
换一下:
| #include <stdio.h> /* get REG_RIP from ucontext.h */ #ifndef __USE_GNU # define __USE_GNU #endif #include <signal.h> //放这里就可以 #include <ucontext.h> int main(int argc, char* argv[]) { printf("%dn", REG_R8); return 0; } |
看下在gcc下,两者的预处理差别: /usr/include/features.h 里面,首先会:
然后根据_GNU_SOURCE来定义:
| #ifdef _GNU_SOURCE # define __USE_GNU 1 #endif |
__USE_GNU 不是开放给用户用的,features.h里面会修改,但 _GNU_SOURCE 不会,它才是给用户用的 看features.h里的注释: These are defined by the user (or the compiler) to specify the desired environment: _GNU_SOURCE All of the above, plus GNU extensions. These are defined by this file and are used by the header files to decide what to declare or define: __USE_GNU Define GNU extensions. 修改方法,在代码最开始,添加:
|
#ifdef
_GNU_SOURCE
# define
_GNU_SOURCE
#endif
|
或者,直接在编译选项里定义。
而gcc和g++的默认定义也有区别,因为g++默认定义了_GNU_SOURCE,所以g++可以编译过而gcc编译不过。
在这里 http:///questions/5679267/how-to-resolve-reg-eip-undeclared-first-use-in-this-function-error-on-linux-3 也搜索到答案,但是之前没有太留意。
I believe you should either have #define _GNU_SOURCE as the first line of your source file, or better put -D_GNU_SOURCE in your CFLAGS (on the command line). Then make sure you include and .
|