出于学习目的,我正在开发一个简单的程序,并且看到以下行为:
如果我尝试使用getenv读取环境变量,它将按预期工作:
/usr/bin/git
如果不包含stdlib.h,则会收到预期的警告:
#include <stdio.h>
#include <stdlib.h>
int main() {
printf("PATH is %s", getenv("PATH"));
return 0;
}
程序仍在编译。使用标头运行该程序会按预期运行,不包含标头的程序会出现段错误。
如果我检查了两个程序的反汇编,就会发现有一个对getenv @ PLT的调用
env.c:7:26: warning: implicit declaration of function ‘getenv’; did you mean ‘getline’? [-Wimplicit-function-declaration]
当我输出两个程序的反汇编时(c源代码中唯一的区别是标头包括),我看到的唯一区别是当我们包含标头时,有一条指令将%eax设置为0打电话给getenv。
call getenv@PLT
如果我在不包含标头的情况下进入gdb程序,它将跳入getenv并在c运行时中运行大量代码。
我想知道为什么不包含标头会导致这种行为的确切原因是什么? c为什么要让它编译?
一些信息: gcc版本7.4.0(Ubuntu 7.4.0-1ubuntu1〜18.04.1) 我正在这样编译: gcc -O0 -S env.c
答案 0 :(得分:2)
在C语言中,如果忘记了包含头文件,则getenv()
函数将被解释为int getenv(...)
。如果包含头文件,则getenv()
函数将被解释为char* getenv(const char*)
。由于printf()
的实现,您情况的唯一区别是返回值的大小。如果为sizeof(int) == sizeof(char*)
,则表示没有问题(对于32位程序,会发生这种情况)。如果为sizeof(int) != sizeof(char*)
,则会出现错误(对于64位程序,会发生这种情况)。这在注释#5