【问题标题】:How program find global variable inside stack?程序如何在堆栈中找到全局变量?
【发布时间】:2019-02-16 02:11:10
【问题描述】:

据我所知,当我声明全局变量int my_var;时,
它位于<bss>(未初始化的全局数据)或<.rodata>(初始化全局数据)部分的固定地址

例如)

int my_var;          // <= It is at <.bss> section
int my_var = 0x1337; // <= It is at <.rodata> section

所以,程序可以使用固定地址找到那些静态值。

问题:但是,我听说全局变量位于&lt;stack&gt;

C运行时启动初始化全局变量:__environ,program_invocation_name
它们位于&lt;stack&gt;....,这意味着它的地址不固定。

问题。程序如何在stack(非固定区域)中找到全局变量?

【问题讨论】:

  • 如您所见,全局变量并不存储在堆栈中。如果是,第一个问题是:哪个堆栈,因为每个线程都有自己的专用堆栈分配给它。
  • 为什么同一个主题有两个不同的问题? stackoverflow.com/questions/52275427/…
  • int my_var = 0x1337; 不能进入 .rodata,除非它是 const,否则会导致 my_var++ 段错误。它实际上会进入.data

标签: assembly x86 binary stack global-variables


【解决方案1】:

您能否提供一个示例或参考一本书,说明存储在堆栈中的全局变量?

堆栈的重点是根据(临时)变量的范围分配内存,因此将堆栈用于“始终存在”的变量是没有意义的(正如您所说,还有另一个用于此目的的部分)。

关于您的示例 (int my_var = 0x1337;),初始化变量可能不会分配在只读部分,因为这并不意味着它不会在某个时刻被修改(除了编译器的决定)。

问题。程序如何在栈(非固定区域)内找到全局变量?

堆栈是一个后进先出队列,其中有一个指针指示最新位置,每个时间变量都有一个地址(创建时,在堆栈边界内)指示其位置,直到它被销毁(超出范围)并且堆栈指针被更新。但是环境变量不存储在堆栈上,它们在它上面:https://www.thegeekstuff.com/2012/03/linux-processes-memory-layout/

【讨论】:

  • 是的。您可以使用 debbuger 轻松找到 global variable in stack 示例。只需附加调试器任何简单的程序,然后输入gdb&gt; x/s program_invocation_name。这是用于打印program_invocation_name 的命令,它是自动初始化的全局变量。然后,您会发现这个值位于堆栈内存区域,即使它是一个全局变量。
  • @최지원:它可能是一个指向栈内存的指针,argv[0]指向的字符串在进程启动之前由内核存储。指针 value 本身存储在.bss 中,您可以通过查看&amp;program_invocation_name 看到它。哦,mevets 已经将此作为答案发布了。
  • @PeterCordes 感谢您的回答,根据您的建议,我可以在mybinary.bss 中找到变量&amp;program_invocation_name!然而,在某些二进制文件中,&amp;program_invocation_namelibc.data 中,而不是在mybinary.bss 中。你知道为什么吗?是因为......也许......编译器版本问题或类似的东西?
  • @최지원:可能取决于你如何在 C 源代码中声明它,是否覆盖库的符号。
  • @PeterCordes 感谢您每次都给我一个很好的答案。 :)
【解决方案2】:

__environ 等...不在堆栈内;它们是普通的全局变量,它们是指向堆栈中位置的指针(即,其值为地址的变量)。初始程序环境、参数等在堆栈中的事实是一个实现细节。它们可以很容易地分配到堆中,或者在其他区域中以适应运行时。

唯一重要的是运行时启动和操作系统就在哪里找到它们达成一致。

[回复评论] 下面的程序应该说明:

#include <stdio.h>
extern char **environ;

int main() {
 int x;
 printf("&envrion  = %p\n", &environ);
 printf("environ   = %p\n", environ);
 printf("*environ  = %p [%s]\n", *environ, *environ);
 printf("&x        = %p\n", &x);
 return 0;
}

在我的系统上,当运行 (cc -static x.c; ./a.out) 时,会生成:

&envrion  = 0x6bbda8
environ   = 0x7ffdd6edb3e8
*environ  = 0x7ffdd6edb9a2 [CLUTTER_IM_MODULE=xim]
&x        = 0x7ffdd6edb2a4

请注意 &environ 与 environ、*environ 和 &x 的地址有很大不同。那是因为后者在堆栈内,而 environ 本身不在。

【讨论】:

  • 你的意思是..“程序有全局变量X,它在堆栈中保存__environ的地址,操作系统可以使用全局变量X找到__environ”。我理解正确吗?
  • 感谢您详细而周到的回复! :D
猜你喜欢
  • 2013-06-27
  • 1970-01-01
  • 1970-01-01
  • 2014-06-08
  • 1970-01-01
  • 2014-04-24
  • 2021-06-30
  • 2017-10-21
  • 2016-12-18
相关资源
最近更新 更多