【发布时间】:2019-07-15 04:40:57
【问题描述】:
我正在开发一个用于学习目的的简单程序,我看到以下行为:
如果我尝试使用 getenv 读取环境变量,它会按预期工作:
#include <stdio.h>
#include <stdlib.h>
int main() {
printf("PATH is %s", getenv("PATH"));
return 0;
}
如果我不包含 stdlib.h,我会收到预期的警告:
env.c:7:26: warning: implicit declaration of function ‘getenv’; did you mean ‘getline’? [-Wimplicit-function-declaration]
程序仍在编译。运行带有标头的程序按预期运行,不包含标头的程序会出现段错误。
如果我检查这两个程序的反汇编,我发现有一个调用 getenv@PLT
call getenv@PLT
当我输出 2 个程序的反汇编时(c 源代码中唯一的区别是头文件包含),我看到的唯一区别是,当我们包含头文件时,有一条指令将 %eax 之前设置为 0调用 getenv。
movl $0, %eax
如果我在 gdb 中单步执行没有包含标头的程序,它会跳转到 getenv 并在 c 运行时运行大量代码。
我想知道为什么不在这里包含标题会导致这种行为的确切原因是什么?为什么 c 让这个编译?
一些信息: gcc 版本 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04.1) 我是这样编译的: gcc -O0 -S 环境.c
【问题讨论】:
-
试试
gcc -Wall -Wextra -pedantic。 -
它假定函数返回一个
int并误解了结果。不要这样做。 -
为什么不把生成的汇编代码贴在这里?
-
如果您正在编译 64 位,这是因为
int和指针具有不同的大小,并且返回指针的未声明的getenv被视为返回int。但即使在这种情况下,汇编代码也应该有其他区别,而不仅仅是将 eax 设置为零;在printf调用之前压入堆栈的参数应该有所不同。
标签: c