2011-10-02 51 views
1

後續行動如何查看GDB中自動變量的內存地址?

嗯我不知道我是否做正確的事情。 感謝所有幫助到目前爲止

我以前的主題: 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不會工作,因爲沒有活動的寄存器(記住程序終止 - 沒有斷點!)。所以像info locals,info寄存器這樣的命令不可用。

我花了整整一天的時間試圖弄清楚發生了什麼事情。我非常感謝所有的幫助,我期待着獲得更多。謝謝。

我該怎麼辦?我需要看看變量a,b,c的值。如何才能做到這一點?

非常感謝。


不是真的是功課,而是課堂討論。

回答

1

這些變量沒有一個特定的內存位置。他們是堆棧變量。因此,在程序終止後,您不能依賴它們在內存中,因爲它們在創建它們的函數返回後會被視爲超出範圍,從而允許它們駐留的地址被重新用於存儲其他內容。

假設你有它的來源是這樣一個功能:

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

如果調用foo(1),變量y將在兩個不同的內存地址,每一個兩個創建的兩個堆棧幀的存在嵌套調用foofoo(1)foo(0))。如果您撥打foo(10),將會有11個實例y,每個實例都擁有不同的值並位於不同的內存地址。

如果您不使用斷點,則所有意圖和目的的變量都不存在。它們只有在程序運行時才分配存儲空間,當前棧中包含它們駐留的函數的一個框架。你不能抓取他們postmortem(除了核心轉儲,這是一種形式的斷點)。總結:如果在程序運行時不分析程序,可以通過中斷調試程序或添加一些代碼來打印/設置值,但不能檢查堆棧變量。這些是堆棧變量。如果你必須讓它們成爲單實例,你應該通過將它們移到函數作用域之外來讓它們堆分配全局變量。

+0

感謝您的意見。我的天啊。是。你非常正確。但是從解密代碼中,我們知道程序的入口地址。我們不能只減少4個字節嗎?如果我們仍在運行程序,它應該是第一個局部變量的地址,int a。請更正我的術語:當我們談論$ ebp - 0x4時,我們仍然可以使用「地址」作爲「位置」的別名,對吧? – CppLearner

+1

@JohnWong程序的入口地址是'main'函數的地址。這與'main'的堆棧幀的位置無關。 *代碼*在內存中的一個地方,它使用的* data *在另一個地方(在這種情況下,在堆棧頂部)。事實並非如此,特定的函數總是將其堆棧幀放置在同一個點上;如果這是真的,則遞歸函數不可能存在。堆棧變量的實例不在構成函數的指令所在的位置附近。 – Borealid

+1

@JohnWong想象一下食譜書 - 「main」是餅乾的食譜。 'a','b'和'c'是成分。你不會把蛋糕存放在**食譜書中。每次想要製作食譜時,都可以將它們從冰箱中取出並放在櫃檯上的新空間中。入口點是食譜書中的書籤。計數器空間是堆棧。完成烹飪和清理後,櫃檯是空的,食譜書中仍然有相同的東西 - 但沒有雞蛋! – Borealid

相關問題