#include <unistd.h> #include <stdio.h> extern char **environ; int main(int argc, char *argv[]) { int i = 0; while(environ[i]) { printf("%s\n", environ[i++]); } return 0; }
这是我的操作:
(gdb) n 8 printf("%s\n", environ[i++]); (gdb) p environ[i] Cannot access memory at address 0x0 (gdb) n LOGNAME=root 7 while(environ[i]) {
正如你所看到的, printf
可以打印出environ[i]
,但是p environ[i]
给我Cannot access memory at address 0x0
,为什么?
gdb解决了错误的environ
符号。 我不知道为什么。 看下面为什么。
但是你可以测试它。 将程序更改为:
#include <unistd.h> #include <stdio.h> extern char **environ; int main(int argc, char *argv[]) { int i = 0; printf("%p\n", &environ); while(environ[i]) { printf("%s\n", environ[i++]); } return 0; }
现在让我们在调试器中运行它。
(gdb)n 7 printf(“%p \ n”,&environ); (gdb)n 0x8049760 8 while(environ [i]){ (gdb)p&environ $ 1 =(char ***)0x46328da0 (GDB)
所以。 在链接过程中,实际的程序已经被解析为地址0x8049760。 当gdb想要访问environ
符号时,它解析为0x46328da0,这是不同的。
编辑。 看来你的environ
符号实际上与environ@@GLIBC_2.0
符号相连。 在gdb中写这个:
(gdb)p
然后按Tab键(两次),它会自动完成符号。 这产生:
(gdb)p 环境@@ GLIBC_2.0
environ@@GLIBC_2.0
是实际链接到extern char **environ
打印时会得到与程序相同的地址0x8049760:
(gdb)p&'environ @@ GLIBC_2.0' $ 9 =(*)0x8049760 (gdb)p((char **)'environ @@ GLIBC_2.0')[i] $ 10 = 0xbffff6ad“XDG_SESSION_ID = 1”
所以,在一个点glibc不赞成使用environ
符号,并添加了一个新的版本
环境变量可以在C / C ++中使用stdlib.h
定义的函数getenv()
来stdlib.h
。 但是,使用main函数的envp
参数可以使用下面的示例遍历环境变量。
#include <stdio.h> int main(int argc, char *argv[], char *envp[]) { char **next = envp; while (*next) { printf("%s\n", *next); next++; } return 0; }
在Mac上测试
你的代码没有问题。 我在我的机器上试了一下,并按预期打印了环境。 你不应该需要使用getenv()。
你是否从终端运行这个应用程序? 如果不是,你应该是。 执行应用程序的其他方法可能是调用你的二进制文件而不传递它的环境。
当你运行“env”时,从终端输出什么? 它应该输出与你的程序相同的列表。 它在我的机器上。
就像grundprinzip说的那样,使用getenv(sz) 并且记得空值检查返回值
或者,
#include <unistd.h> #include <stdio.h> int main(int argc, char *argv[], char*[] environ) { int i = 0; while(environ[i]) { printf("%s\n", environ[i++]); } return 0; }
可能调试过程开始于
execve(binary, NULL, NULL);
即使有一个可用的环境, extern char **environ
也会获得第二个NULL
。
稍作改动,你的程序可以独立运行,也可以在gdb
下运行。
/* #include <unistd.h> */ /* no more environ */ #include <stdio.h> /* extern char **environ; */ /* no more environ */ int main(int argc, char *argv[]) { int i = 0; char **ptr = argv + argc + 1; /* points to environment, in Un*x */ while(ptr[i]) { printf("%s\n", ptr[i++]); } return 0; }
为什么,以及如何, NULL
被转换为gdb
内的适当的值我不知道。