2013-04-04 86 views
62

這個問題來自回答堆棧溢出問題Why do books say, 「the compiler allocates space for variables in memory」?,其中我試圖向OP演示當您在堆棧中分配變量以及編譯器如何生成知道要分配的內存大小的代碼時會發生什麼。顯然,編譯器分配的空間比需要的多得多。爲什麼在堆棧上分配這麼多空間?

然而,編譯時以下

#include <iostream> 
using namespace std; 

int main() 
{ 
    int foo; 
    return 0; 
} 

你得到的Visual C++ 2012年在調試模式下編譯沒有的優化以下彙編輸出:

int main() 
{ 
00A31CC0 push  ebp 
00A31CC1 mov   ebp,esp 
00A31CC3 sub   esp,0CCh // Allocates 204 bytes here. 
00A31CC9 push  ebx 
00A31CCA push  esi 
00A31CCB push  edi 
00A31CCC lea   edi,[ebp-0CCh] 
00A31CD2 mov   ecx,33h 
00A31CD7 mov   eax,0CCCCCCCCh 
00A31CDC rep stos dword ptr es:[edi] 
    int foo; 
    return 0; 
00A31CDE xor   eax,eax 
} 

再增加一個int到我的計劃使得註釋行以上爲以下:

00B81CC3 sub   esp,0D8h // Allocate 216 bytes 

@JamesKanze在我的回答中提到的問題是,爲什麼編譯器,顯然它不僅是Visual C++(我還沒有用另一個編譯器做實驗),分別分配了204和216字節,在第一個它只需要四個,第二個只需要八個?

該程序創建一個32位可執行文件。

從技術角度來看,爲什麼需要分配204個字節而不是4個?

編輯:

調用兩個功能,創造一個double,並在兩個主要int,你

01374493 sub   esp,0E8h // 232 bytes 

出於同樣的程序與上述編輯,它這樣做在釋放模式(沒有優化):

sub esp, 8    // Two ints 
movsd QWORD PTR [esp], xmm0 // I suspect this is where my `double` goes 
+10

由於它是調試模式。 – ForEveR 2013-04-04 08:58:53

+2

你有比較稍微更復雜的主要調用一些功能?我知道g ++只是分配足夠的空間用於函數參數。不知道關於visual C++ – 2013-04-04 08:59:12

+9

調試模式可以包含各種堆棧守衛等等。它在釋放模式下的表現如何? – Angew 2013-04-04 09:00:47

回答

101

該額外空間由/ Zi編譯選項生成。這使編輯+繼續。額外的空間可用於在調試時編輯代碼時可能添加的局部變量。

你也看到/ RTC的效果,它初始化所有局部變量0xcccccccc,這樣很容易診斷,因爲有忘記初始化變量的問題。當然,這些代碼在默認的發佈配置設置中都不會生成。

+7

啊哈。我沒有想到這一點。 (我知道一些編譯器在每個函數之間留出了額外的空間,完全是出於這個原因,但是對於本地變量來說,同樣是不可缺少的。) – 2013-04-04 09:21:45