GCC指定-I/usr/include/linux编译报size_t未定义原因排查
问题根因
gcc的-I参数指定的头文件搜索路径,优先级高于系统默认的用户态标准头文件搜索路径。手动添加/usr/include/linux到搜索路径后,编译器会优先加载该目录下的内核专用头文件,替换掉glibc提供的符合C标准的用户态头文件,最终触发类型未定义错误。
头文件搜索机制的具体变化
- gcc默认头文件搜索优先级为:命令行
-I指定路径 > 头文件相关环境变量配置的路径 > 系统默认标准头文件目录(如/usr/include、/usr/include/x86_64-linux-gnu等)。开启verbose模式无法排查到该问题的原因是,verbose仅会打印待搜索的目录列表,不会输出每个#include指令实际匹配到的头文件完整路径,因此很难直接观察到头文件被错误替换的情况。 /usr/include/linux目录下存放的是Linux内核编译专用的头文件,和glibc提供的用户态标准头文件存在大量重名,但内容仅服务于内核态代码逻辑,不满足C标准/POSIX标准对用户态接口的定义要求。- 本次报错的直接触发点:标准库头文件
stdio.h依赖stddef.h中定义的size_t类型,添加-I/usr/include/linux后,编译器优先加载了该目录下的内核版stddef.h,这个头文件没有给用户态程序定义size_t,因此抛出一连串unknown type name 'size_t'错误。
复现报错信息
gcc -o check -I/usr/include/linux check.c
In file included from /usr/include/stdio.h:43, from check.c:1: /usr/include/x86_64-linux-gnu/bits/types/struct_FILE.h:95:3: error: unknown type name 'size_t' 95 | size_t __pad5; | ^~~~~~ /usr/include/x86_64-linux-gnu/bits/types/struct_FILE.h:98:67: error: 'size_t' undeclared here (not in a function) 98 | char _unused2[15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size_t)]; | ^~~~~~ /usr/include/x86_64-linux-gnu/bits/types/struct_FILE.h:1:1: note: 'size_t' is defined in header '<stddef.h>'; did you forget to '#include <stddef.h>'? +++ |+#include <stddef.h> 1 | /* Copyright (C) 1991-2020 Free Software Foundation, Inc. /usr/include/stdio.h:292:35: error: expected declaration specifiers or '...' before 'size_t' 292 | extern FILE *fmemopen (void *__s, size_t __len, const char *__modes) | ^~~~~~ /usr/include/stdio.h:298:47: error: expected declaration specifiers or '...' before 'size_t' 298 | extern FILE *open_memstream (char **__bufloc, size_t *__sizeloc) __THROW __wur; | ^~~~~~ /usr/include/stdio.h:309:34: error: expected declaration specifiers or '...' before 'size_t' 309 | int __modes, size_t __n) __THROW; | ^~~~~~ /usr/include/stdio.h:315:24: error: expected declaration specifiers or '...' before 'size_t' 315 | size_t __size) __THROW; | ^~~~~~ /usr/include/stdio.h:354:44: error: expected declaration specifiers or '...' before 'size_t' 354 | extern int snprintf (char *__restrict __s, size_t __maxlen,
正确处理方式
- 编译普通用户态C程序时,不要手动将
/usr/include/linux加入-I参数,编译器会在需要依赖内核相关头文件时自动按正确顺序搜索该路径,不需要手动指定。 - 如果确实需要引用该路径下的特定头文件,不要全局添加该搜索路径,可在代码中写全路径包含对应头文件,避免污染全局头文件搜索顺序,导致标准头文件被错误替换。
内容的提问来源于stack exchange,提问作者Chitrak Gupta
相关产品推荐
相关产品推荐

