Рассмотрим следующий пример:
struct vector {
int size() const;
bool empty() const;
};
bool vector::empty() const
{
return size() == 0;
}
Сгенерированный код сборки для vector::empty
(по clang, с оптимизацией):
push rax
call vector::size() const
test eax, eax
sete al
pop rcx
ret
Почему он выделяет пространство стека? Это не используется вообще. push
И pop
может быть опущен. Оптимизированные сборки MSVC и gcc также используют пространство стека для этой функции (см. Godbolt ), поэтому должна быть причина.
c++
code-generation
calling-convention
abi
stack-allocation
Доктор гут
источник
источник
this
параметр?vector::size()
не определен в примере, чтобы имитировать, что он не встроен.vector::size()
не имеет отношения к выделению или не выделению стекового фреймаvector::empty()
. Вempty()
нем просто называется, что бы это ни было.Ответы:
Он выделяет пространство стека, поэтому стек выравнивается по 16 байтов. Это необходимо, потому что адрес возврата занимает 8 байтов, поэтому для сохранения 16-байтового стека требуется дополнительное 8-байтовое пространство.
Выравнивание стековых фреймов можно настроить с помощью аргументов командной строки для некоторых компиляторов.
rsp
начала функции, что означает, что что-то еще также влияет на это.-mstack-alignment
опция определяет выравнивание стека. Кажется, что по умолчанию 16, хотя не задокументировано. Если вы установите его на 8, выделение стека (push
иpop
) исчезнет из сгенерированного кода сборки.-mpreferred-stack-boundary
опция определяет выравнивание стека. Если заданное значение равно N, это означает 2 ^ N байтов выравнивания. Значение по умолчанию 4, что означает 16 байтов. Если вы установите значение 3 (т.е. 8 байт), распределение стека (sub
иadd
дляrsp
) исчезнет из сгенерированного кода сборки.Проверьте на Годболт .
источник