To pytanie pochodzi z odpowiedzi na pytanie przepełnienie stosu Why do books say, “the compiler allocates space for variables in memory”?, gdzie próbowałem pokazać OP, co dzieje się, gdy przydzielisz zmiennej na stos i jak generuje kod, który zna rozmiar pamięci do przydzielenia. Wygląda na to, że kompilator przydziela znacznie więcej miejsca niż to, co jest potrzebne.Dlaczego na stosie jest za dużo miejsca?
Jednak podczas kompilowania następujące
#include <iostream>
using namespace std;
int main()
{
int foo;
return 0;
}
uzyskać następujące dane wyjściowe asemblera z Visual C++ 2012 skompilowany w trybie debugowania bez optymalizacji na:
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
}
Dodanie jeden int
do mojego programu powoduje skomentowanie linii powyżej:
00B81CC3 sub esp,0D8h // Allocate 216 bytes
Pytanie postawione przez @JamesKanze w mojej odpowiedzi połączonej na szczycie, to dlaczego kompilator, i najwyraźniej to nie tylko Visual C++ (nie zrobiłem eksperymentu z innym kompilatorem), przydzielone odpowiednio 204 i 216 bajtów, gdzie w pierwszym przypadku potrzebuje tylko czterech, a w drugiej potrzebuje tylko ośmiu?
Ten program tworzy 32-bitowy plik wykonywalny.
Z technicznego punktu widzenia, dlaczego konieczne może być przydzielenie 204 bajtów zamiast tylko 4?
EDIT:
Wywołanie dwie funkcje oraz tworzenie double
i dwa int
w głównym, można uzyskać
01374493 sub esp,0E8h // 232 bytes
Z tego samego programu, jak edytować powyżej, to robi to w trybie zwolnienia (bez optymalizacje):
sub esp, 8 // Two ints
movsd QWORD PTR [esp], xmm0 // I suspect this is where my `double` goes
Ponieważ jest to tryb debugowania. – ForEveR
Czy porównałeś się z nieco bardziej złożonym głównym wywoływaniem niektórych funkcji? Wiem, że g ++ po prostu alokuje wystarczającą ilość miejsca do użycia dla argumentów funkcji. nie wiem o visual C++ –
Tryb debugowania może zawierać wszelkiego rodzaju strażników stosu itp. Jak zachowuje się w trybie zwolnienia? – Angew