7

我有一个指向 C/C++ 变量的指针。是否可以准确地确定该变量属于哪个内存段?如果是,如何?

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

4

4 回答 4

2

找出你的架构是否有指向你的堆或堆栈区域的指针。通常有一些堆栈指针或帧指针..

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

于 2012-08-06T11:51:57.940 回答
2

如果您使用的是 linux(不确定其他 unice),您也许可以在文件中找到信息/proc/<pid>/maps

于 2012-08-06T13:52:05.997 回答
1

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

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

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

调整链接描述文件可能并不容易。使用 gcc,您可以使用以下命令转储它:

gcc -Wl,-verbose whatever.c

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

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

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

于 2012-08-06T13:24:03.593 回答
0

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

样本输出:

0804a020 g     O .bss   00000004              var

它说在地址部分var是一个global 对象O0804a020.bss

于 2012-08-06T14:39:59.750 回答