如何查看GDB中自动变量的内存地址

How can I look into the memory addresses of automatic variables in GDB?

本文关键字:变量 内存 地址 何查看 GDB      更新时间:2023-10-16

跟踪

嗯,我不确定我做的事情是否正确感谢迄今为止提供的所有帮助

我以前的线程:这真的是的地址吗

我正在制作新的线程,因为这实际上是一个单独的问题,也是核心问题。

请耐心等待,谢谢。


让我重申我的目标:

我希望能够查看每个变量的内存地址(我们知道程序的入口地址,也知道读取汇编代码时留出了多少字节(。假设我们得到以下源代码:

源代码

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将不起作用,因为没有活动寄存器(记住程序终止-没有断点!(。所以像info locals、info registers这样的命令是不可用的。

我花了一整天的时间试图弄清楚发生了什么。我真的很感激所有的帮助,我期待着得到更多。谢谢

我该怎么办??我需要看看变量a,b,c的值。如何做到这一点?

非常感谢。


不是真正的家庭作业,而是课堂讨论。

这些变量没有一个特定的内存位置。它们是堆栈变量。因此,在程序终止后,您不能依赖它们在内存中,因为在创建它们的函数返回后,它们被视为超出范围,从而允许它们所在的地址被重新用于存储其他内容。

想象一下,你有一个函数,它的来源如下:

int foo(int x) {
    int y = x;
    if (y == 0) {
        return 0;
    }
    return foo(x-1)+1;
}

如果调用foo(1),变量y将存在于两个不同的内存地址,为foo的两个嵌套调用(foo(1)foo(0)(创建的两个堆栈帧各一个。如果调用foo(10),则会有11个y实例,每个实例都持有不同的值,并驻留在不同的内存地址。

如果不使用断点,那么所有意图和目的的变量都不存在。它们只有在程序运行时才分配存储,并且当前堆栈包含它们所在函数的帧。您无法在死后获取它们(除了从核心转储中获取,这实际上是一种断点形式(。

总结:如果在程序运行时不分析程序,无论是通过中断到调试器,还是通过添加一些将打印/搁置值的代码,都无法检查堆栈变量。这些是堆栈变量。如果必须将它们作为单个实例,则应通过将它们移出函数范围,使它们成为堆分配的全局变量。