如何在内存十六进制转储中找到变量的地址?

3

当我在做“学习C语言的艰苦之路”例子时,我想到:

我设置了int a = 10;但是这个值10实际上在哪里?当我的程序正在运行时,我能手动从外部访问它吗?

这里有一个小的C代码片段供演示:

int main (int argc, char const* argv[]) {                                   

    int a = 10;
    int b = 5;
    int c = a + b;

    return 0;
}   

我打开了GNU项目调试器(GDB),然后输入:

break main
run
next 2

据我所知,0x7fff5bffb04int c的一个内存地址。然后我使用hexdump -C /dev/mem系统调用将整个内存转储到终端中。
现在的问题是,在这个庞大的十六进制转储中,我应该在哪里寻找变量c? 我希望能够根据地址0x7fff5bffb04找到它的值,即15。此外,奖励问题是,hexdump -C中的每一列代表什么?(我知道最后一列是ASCII表示)
请看下方图片:
gdb
hex dump

3
0x7f...这个地址是虚拟的。除非你知道虚拟地址与物理地址之间的映射关系,否则无法使用它来定位物理内存转储文件中的内容。(第一栏是“地址”(从文件开始算起的字节数),最后一栏是ASCII表示,中间是数据。) - Mat
@Mat:谢谢。我能打印物理内存地址吗?或者我可以转储虚拟内存而不是物理内存吗?有什么可能的解决方案? - Sahat Yalkabov
你为什么将argv定义为char const *[] - obataku
@TwilightPonyInc.:这没有什么实际作用(你需要内核代码才能做到)。“有可能的解决方案是什么?”- 不清楚你实际的问题是什么。如果你正在尝试理解一个原始的完整系统内存转储,那么你面临着一个非常复杂的任务。根据你具体要做的事情,可能会有简化它的方法。 - Mat
1
不要使用 /dev/mem,而是使用 /proc/pid/mem,其中_pid_是运行您的程序的进程ID(注意:不是gdb进程)。 - Barmar
显示剩余3条评论
2个回答

3
我随后使用了hexdump -C /dev/mem系统调用将整个内存转储到终端中。
你的hexdump转储了物理内存地址。地址0x7fff5bffb04是你正在调试的进程中变量的虚拟地址。它映射到一些物理地址,但是如果不检查内核映射表(正如Mat在评论中告诉你的那样),你将无法找到它所映射的物理地址。
要检查虚拟地址空间,请使用/proc//mem(正如Barmar在评论中已经告诉你的那样)。
但这整个练习是没有意义的,因为你已经可以在GDB中检查虚拟内存,并且当你查看GDB没有更方便地显示给你的虚拟内存时,你将什么也看不到[1]。
[1] 除非你能看到GDB插入的断点,但是你不需要理解这一点 :-)

1
首先,没有理由让这些值存在于内存中。很可能这个程序的机器码只是将这些值存储在CPU寄存器中。你需要更多的字节(至少尝试512个)并将它们设置为随机值,然后你可以在内存转储中搜索这些值。
你最好查看C编译器生成的汇编代码。

“没有理由让这些值存在于内存中”——是有的。当程序没有进行优化构建时(就像这里的情况一样),大多数编译器会在堆栈上保留空间,并实际将这些值保存在那里。如果程序进行了优化构建,那么这些值存在于寄存器中也没有理由:任何一个好的编译器都会优化掉所有的赋值操作,因为它们的结果没有被使用。 - Employed Russian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接