简体   繁体   English

为什么我无法打印出 gdb 中的环境变量?

[英]Why I can't print out environment variables in gdb?

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

Here's my ops:这是我的操作:

(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]) {

As you can see, printf can print out environ[i] ,but p environ[i] gives me Cannot access memory at address 0x0 ,why?如您所见, printf可以打印出environ[i] ,但是p environ[i]给了我Cannot access memory at address 0x0 ,为什么?

gdb resolves the wrong environ symbol. environ解决了错误的环境符号。 I don't know why though.我不知道为什么。 See below as to why.至于为什么,请参见下文。

But you can test it.但是你可以测试一下。 Change the program to:将程序更改为:

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

Now let's run this in the debugger.现在让我们在调试器中运行它。

(gdb) n
7         printf("%p\n", &environ);
(gdb) n
0x8049760
8         while(environ[i]) {
(gdb) p &environ
$1 = (char ***) 0x46328da0
(gdb)

So.所以。 The actual program has, during its linking, resolved environ to the address 0x8049760.实际程序在其链接期间已将环境解析为地址environ When gdb wants to access the environ symbol, it resolves to 0x46328da0, which is different.当 gdb 想要访问environ符号时,它解析为 0x46328da0,这是不同的。

Edit.编辑。 It seems your environ symbol is actually linked to the environ@@GLIBC_2.0 symbol.看来您的environ符号实际上链接到environ@@GLIBC_2.0符号。 In gdb write this:在 gdb 中写下:

(gdb) p environ

And hit the tab key (twice), it'll autocomplete the symbols.并按 Tab 键(两次),它会自动完成符号。 Which yields:产生:

(gdb) p environ
environ             environ@@GLIBC_2.0

environ@@GLIBC_2.0 is the one actually linked to the extern char **environ environ@@GLIBC_2.0是实际链接到extern char **environ的那个

Printing this yields the same address as the program sees, 0x8049760:打印它会产生与程序看到的地址相同的地址,0x8049760:

(gdb) p &'environ@@GLIBC_2.0'
$9 = ( *) 0x8049760
(gdb) p ((char**)'environ@@GLIBC_2.0')[i]
$10 = 0xbffff6ad "XDG_SESSION_ID=1"

So, at one point glibc deprecated the environ symbol, and added a newer version因此,glibc 一度弃用了environ符号,并添加了一个更新的版本

Environment variables are accessed in C/C++ using the function getenv() defined in stdlib.h .使用stdlib.h中定义的 function getenv()在 C/C++ 中访问环境变量。 However, using the envp parameter of the main function you can use the following example to iterate over environment variables.但是,使用主envp的 envp 参数,您可以使用以下示例来迭代环境变量。

#include <stdio.h>

int main(int argc, char *argv[], char *envp[])
{
  char **next = envp;

  while (*next) 
  {
    printf("%s\n", *next);
    next++;
  }
  return 0;


}

Tested on a Mac在 Mac 上测试

Like grundprinzip said, use getenv(sz) and remember to null-check the return value就像 grundprinzip 所说,使用 getenv(sz)并记住对返回值进行空检查

Alternatively,或者,

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

Probably the process under debugging is started with可能正在调试的过程是从

execve(binary, NULL, NULL);

and the extern char **environ gets that 2nd NULL even though there's an environment available.即使有可用的环境, extern char **environ也会得到第二个NULL

With a little change, your program works both standalone and under gdb .稍作改动,您的程序既可以独立运行,也可以在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;
}

Why, and how, that NULL gets converted to the proper value inside gdb I have no idea.为什么以及如何将NULL转换为gdb内的正确值,我不知道。

There's nothing wrong with your code.你的代码没有问题。 I tried it on my machine and it printed the environment as expected.我在我的机器上试了一下,它按预期打印了环境。 You should not need to use getenv().您不需要使用 getenv()。

Are you running this application from the terminal?您是否从终端运行此应用程序? If not, you should be.如果不是,你应该是。 Other means of executing an application might be calling your binary without passing it the environment.执行应用程序的其他方法可能是调用您的二进制文件而不将其传递给环境。

From the terminal what is your output when you run "env"?从终端运行“env”时,您的 output 是什么? It should output the same list as your program.它应该 output 与您的程序相同的列表。 It does on my machine.它在我的机器上。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM