本文转载至:http://mnstory.net/2015/03/_gnu_source-vs-__use_gnu/#more-371
c-cpp.c:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
#include
#include
/* get REG_RIP from ucontext.h */
#ifndef __USE_GNU
# define __USE_GNU
#endif
#include
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显示为:
1
2
3
|
typedef
greg_t
gregset_t
[
23
]
;
# 94 "/usr/include/x86_64-linux-gnu/sys/ucontext.h" 3 4
struct
_libc_fpxreg
|
g++.c显示为:
1
2
3
4
5
6
7
8
|
typedef
greg_t
gregset_t
[
23
]
;
enum
{
REG_R8
=
0
,
REG_R9
,
.
.
.
}
;
struct
_libc_fpxreg
|
很明显,gcc版本的,没有enum,所有gcc编译不过。
换一下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
#include
/* get REG_RIP from ucontext.h */
#ifndef __USE_GNU
# define __USE_GNU
#endif
#include
#include
int
main
(
int
argc
,
char
*
argv
[
]
)
{
printf
(
"%dn"
,
REG_R8
)
;
return
0
;
}
|
看下在gcc下,两者的预处理差别:
/usr/include/features.h 里面,首先会:
1
|
#undef __USE_GNU
|
然后根据_GNU_SOURCE来定义:
1
2
3
|
#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.
修改方法,在代码最开始,添加:
1
2
3
|
#ifdef _GNU_SOURCE
# define _GNU_SOURCE
#endif
|
或者,直接在编译选项里定义。
而gcc和g++的默认定义也有区别,因为g++默认定义了_GNU_SOURCE,所以g++可以编译过而gcc编译不过。
在这里 http://stackoverflow.com/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 .