Почему так много места в стеке?


этот вопрос исходит из ответа на вопрос переполнения стека почему в книгах говорится:"компилятор выделяет пространство для переменных в памяти"?, где я попытался продемонстрировать 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?

EDIT:

вызов двух функций и создание 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
1 62

1 ответ:

Это дополнительное пространство генерируется параметром компиляции /Zi. Что позволяет редактировать + продолжить. Дополнительные места для локальных переменных, которые можно добавить при редактирование кода во время отладки.

вы также видите эффект /RTC, он инициализирует все локальные переменные в 0xcccccccc, так что легче диагностировать проблемы из-за забывания инициализировать переменные. Конечно, ни один из этого кода не создается в настройках конфигурации выпуска по умолчанию.