Когда выделяется память под автоматические переменные?
В книгах пишут, что когда выполнение программы заходит в функцию, то выделяется память под все автоматические переменные функции при вхождении и она освобождается при завершении этой функции. Например:
void function(int value)
{
int a = 10;
// ...
double b = 6.3;
for (size_t i = 0; i < 10; ++i)
{
// ...
}
}
Память под все переменные (value, a, b, i) выделяется при вхождении в функцию или при объявлении?
Ответы (1 шт):
Память может быть выделена во время вызова функции, когда указатель на вершину стека сдвигают на определенное количество байт, чтобы зарезервировать место под локальные переменные. Например, код
void function(int value) { int a = 10; double b = 6.3; }будет скомпилирован (
-O0 -mno-red-zone -m32) вfunction(int): push ebp mov ebp, esp // Резервируем 16 байт под локальные переменные. Помните, // что на x86 стек растет по направлению к младшим адресам, // поэтому мы ВЫЧИТАЕМ из регистра esp. sub esp, 16 mov DWORD PTR [ebp-4], 10 fld QWORD PTR .LC0 fstp QWORD PTR [ebp-16] nop leave retНа практике в системах с System V ABI такое выделение памяти под локальные переменные вообще не происходит. По соглашению вызываемая функция может свободно использовать 128 байт после указателя на вершину стека для хранения своих локальных переменных. Эта свободная область в 128 байт называется Red zone.
Именно поэтому, чтобы продемонстрировать выделение памяти в примере выше, пришлось передать компилятору флаг
mno-red-zone.Локальная переменная может быть помещена в регистр, тогда память под нее вообще не будет выделена.
Мы можем использовать ключевое слово
registerпри объявлении переменной, чтобы посоветовать компилятору поместить переменную в регистр. Хотя такие советы компилятор по большей части игнорирует.Копилятор может встроить значение локальной переменной в саму инструкцию процессора, тогда память под переменную также не будет выделена.
В процессе оптимизации компилятор может вообще избавится от некоторых локальных переменных, следовательно, и память для них выделена не будет.
Например, следующий код
int foo(void) { int a = 4; int b = 9; return a + b; }будет скомпилирован (
-O2) вfoo: mov eax, 13 ret