后续
嗯,我不确定我做的是否正确。 感谢迄今为止的所有帮助。
我以前的帖子: Is this really the address
我正在创建新线程,因为这确实是一个单独的问题,也是核心问题。
请耐心等待,谢谢。
让我重申一下我的目标:
我希望能够查看每个变量的内存地址(我们知道程序的入口地址,并且我们知道在读取汇编代码时会留出多少字节)。假设我们得到以下源代码:
源代码
int main()
{
int a = 15;
int b;
int c;
b = c;
c = c+1;
return 0;
}
我们应该能够找到变量a和c的地址,以及这些内存地址中的值。
使用gdb布局asm我得到了这个
│0x80483f4 <main()> push %ebp │
│0x80483f5 <main()+1> mov %esp,%ebp │
│0x80483f7 <main()+3> sub $0x10,%esp │
│0x80483fa <main()+6> movl $0xf,-0x4(%ebp) │
│0x8048401 <main()+13> mov -0x8(%ebp),%eax │
│0x8048404 <main()+16> mov %eax,-0xc(%ebp) │
│0x8048407 <main()+19> addl $0x1,-0x8(%ebp) │
│0x804840b <main()+23> mov $0x0,%eax │
│0x8048410 <main()+28> leave │
│0x8048411 <main()+29> ret │
│0x8048412 nop
// the statement int a = 15 is in the address 0x80483fa
// I want to get the value 15
x/w 0x80483fd <== this will print 15
但这对我没有意义,因为根据我的回忆,变量应该在ebp - 0x10中吗?
// the starting address of the program is 0x80483f4
// minus 0x10 we get 0x80483E4
x/w 0x80483E4 <== will print a big number
// Since b = c, I should be able to get that as I decrement, but no luck
我不认为我知道我在做什么......?一方面,一旦程序终止,自动变量就会被销毁......
PS:我真的不能在调试时使用cout,printf或设置断点或观察器。
所以打印$ ebp将无效,因为没有活动寄存器(记住程序终止 - 没有断点!)。因此,信息本地,信息寄存器等命令不可用。
我一整天都在努力弄清楚发生了什么。我非常感谢所有的帮助,我期待得到更多。谢谢。
我该怎么办?我需要查看变量a,b,c的值。如何才能做到这一点?
非常感谢。
不是真正的家庭作业,而是课堂讨论。
答案 0 :(得分:1)
这些变量没有一个特定的内存位置。它们是堆栈变量。因此,在程序终止后,您不能依赖它们在内存中,因为它们在创建它们的函数返回后被视为超出范围,允许它们所在的地址被重用用于存储其他内容。
想象一下,你有一个源代码如下的函数:
int foo(int x) {
int y = x;
if (y == 0) {
return 0;
}
return foo(x-1)+1;
}
如果你调用foo(1)
,变量y
将存在于两个不同的内存地址,一个用于为foo
的两个嵌套调用创建的两个堆栈帧中的每一个({{ 1}}和foo(1)
)。如果您致电foo(0)
,将会有11个foo(10)
个实例,每个实例持有不同的值并位于不同的内存地址。
如果不使用断点,则不存在所有意图和目的的变量。它们仅在程序运行时分配存储,并且当前堆栈包含来自它们所驻留的函数的帧。你不能在死后抓住它们(除了核心转储,这实际上是断点的一种形式)。
总结:如果您在程序运行时不分析程序,无论是通过打破调试器还是通过添加一些将打印/预留值的代码,您都无法检查堆栈变量。这些是堆栈变量。如果必须将它们作为单实例,则应通过将它们移出函数范围来使它们成为堆分配的全局变量。