识别地址是属于堆还是堆栈还是寄存器

我有一个指针可用于C / C ++变量。 是否有可能准确地确定此变量属于哪个内存段? 如果有,怎么样?

注意:我只有这个变量的地址,如果变量是本地/全局等,则没有进一步的信息。

了解您的体系结构是否具有指向堆或堆栈区域的指针。 通常有一些stackpointers或framepointers ..

然后将您的实际地址与这些地址进行比较,并确定它们的归属。

如果您使用的是linux(不确定其他unices),您可以在文件/proc//maps找到相关信息。

您可以首先确定可执行文件中不同部分的开头和结尾。 为此,您需要最终在链接器脚本中围绕每个部分添加一些变量,如下所示:

 SECTIONS { [...] .data : { data_start = .; *(.data) data_end = .; } [...] } 

然后,您可以在C / C ++代码中将这些变量声明为外部变量,并直接使用它们来比较您要识别的地址。

调整链接器脚本可能并不容易。 使用gcc,您可以使用以下命令转储它:

 gcc -Wl,-verbose whatever.c 

然后尝试查找已经在(杂乱)输出中定义的变量。

要获得堆栈的边界,您可以在main()函数的开头实例化一个虚拟变量,并将其地址保存为堆栈的顶部,然后在当前位置实例化另一个,这将使您获得底部。 但请注意,编译器的行为可能与此不完全相同(C中的变量的堆栈顺序无法保证,甚至不使用堆栈)因此这应该可以工作但不可移植。

最后,对于堆,我没有技巧。 我只是推断出一个不在data / bss /派生而不在堆栈中的变量会在堆中(不包括寄存器,但如果你能得到地址,我敢打赌编译器永远不会使用只有寄存器的存储)。

我不确切知道它是否适合您的情况,但您可以尝试使用objdump -t来查看elf文件的符号表。 您所需要的只是变量的地址。 在那里你可以找到标志,显示每个变量的部分。 有关更多详细信息,请参阅objdump手册页。

样本输出:

 0804a020 g O .bss 00000004 var 

它表示var是地址0804a020 ,部分.bssg lobal O 0804a020