为什么我不能在gdb中打印出环境变量?

时间:2011-06-01 15:13:11

标签: c linux gdb environment-variables

#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,为什么?

5 个答案:

答案 0 :(得分:9)

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)

因此。实际程序在链接期间将environ解析为地址0x8049760。 当gdb想要访问environ符号时,它会解析为0x46328da0,这是不同的。

编辑。 您的environ符号实际上与environ@@GLIBC_2.0符号相关联。 在gdb中写下这个:

(gdb) p environ

然后按Tab键(两次),它会自动填充符号。产量:

(gdb) p environ
environ             environ@@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符号,并添加了更新的版本

答案 1 :(得分:0)

使用getenv()中定义的函数stdlib.h在C / C ++中访问环境变量。但是,使用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上测试

答案 2 :(得分:0)

像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;
}

答案 3 :(得分: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内部的正确值我不知道。

答案 4 :(得分:-1)

您的代码没有任何问题。我在我的机器上试了一下它按预期印刷了环境。您不应该使用getenv()。

您是否从终端运行此应用程序?如果不是,你应该是。执行应用程序的其他方法可能是调用二进制文件而不将其传递给环境。

从终端运行“env”时输出的是什么?它应该输出与您的程序相同的列表。它在我的机器上。