2013-10-21 27 views
6

我有一個函數:爲什麼我的編譯器保留了比功能堆棧幀所需空間更多的空間?

void func(int a) 
{ 
    int x = a+2; 
} 

在彙編代碼,在功能序言:

push %ebp 
mov %esp, %ebp 
sub $0x10, %esp 

的代碼只需要保留空間對於x即4個字節。但它保留了16個字節。這是爲什麼 ?我一直認爲它會保留比所需更多的空間。

我的猜測:它傾向於存儲在16個字節。即如果我需要說20個字節,它將保留32個字節,無論如何。

+0

看來我的猜測是錯誤的,因爲在這個鏈接中,傢伙只需要16個字節的空間,但32個字節是保留的。 http://stackoverflow.com/questions/13430540/please-i-dont-understand-why-sub-0x20-esp-let-me-know – Rash

+0

可能重複http://stackoverflow.com/questions/4175281/what -does,它均值到ALIGN-的堆棧。 –

+0

你好@PaulGriffiths這不是重複的,因爲這個問題解釋了爲什麼你需要對齊內存。我在問爲什麼超過所需的空間被保留在堆棧中? – Rash

回答

5

這很大程度上取決於您的體系結構和編譯器標誌,因此無法指向單個事物並在此處說「這一定是它」。不過,我可以給你一些你可能會覺得有用的提示。

首先,考慮堆棧邊界。您可能聽說過GCC的-mpreferred-stack-boundary = X標誌。如果沒有,它基本上會告訴你的編譯器優先選擇堆棧中的值爲每個2^X字節。然後你的編譯器會嘗試優化你的程序,以便儘可能使這些值適合堆棧。另一方面,像__packed__這樣的GCC修飾符會使編譯器儘可能緊地將數據放入堆棧。

還有堆棧保護器。基本上,GCC在堆棧中放置了虛擬值,以確保緩衝區溢出除了對程序進行segfaulting(這並不好玩,但比攻擊者加強指令指針的控制要好)之外不會造成任何其他傷害。您可以輕鬆地嘗試這一點:採取任何最新版本的GCC,並讓用戶溢出一個緩衝區。您會注意到程序退出時出現了'堆棧粉碎檢測到,終止'的消息。嘗試用-fno-stack-protector編譯你的程序,並且堆棧中分配的本地內存可能會更小。

+0

注意:這個答案是與我在這裏給出的答案的前半部分相同:http://stackoverflow.com/questions/19736213/explain-esp-ebp-in-this-program/19736689#19736689我不會考慮它是重複的,但你可能會發現它很有用。 – Anonymous

相關問題