Considere el siguiente ejemplo:
struct vector {
int size() const;
bool empty() const;
};
bool vector::empty() const
{
return size() == 0;
}
El código de ensamblaje generado para vector::empty
(por clang, con optimizaciones):
push rax
call vector::size() const
test eax, eax
sete al
pop rcx
ret
¿Por qué asigna espacio de pila? No se usa en absoluto. El push
y pop
podría ser omitido. Las compilaciones optimizadas de MSVC y gcc también usan espacio de pila para esta función (ver en godbolt ), por lo que debe haber una razón.
this
parámetro implícito ?vector::size()
no está definido en el ejemplo para simular que no está en línea.vector::size()
no es relevante para asignar o no asignar un marco de pilavector::empty()
. Enempty()
esto solo se llama, sea lo que sea.Respuestas:
Asigna espacio de pila, por lo que la pila está alineada a 16 bytes. Es necesario, porque la dirección de retorno toma 8 bytes, por lo que se necesita un espacio adicional de 8 bytes para mantener la pila alineada de 16 bytes.
La alineación de los marcos de la pila se puede configurar con argumentos de línea de comandos para algunos compiladores.
rsp
al comienzo de la función, lo que significa que algo más también afecta esto.-mstack-alignment
opción especifica la alineación de la pila. Parece que el valor predeterminado es 16, aunque no está documentado. Si lo establece en 8, la asignación de la pila (push
ypop
) desaparece del código de ensamblado generado.-mpreferred-stack-boundary
opción especifica la alineación de la pila. Si el valor dado es N, significa 2 ^ N bytes de alineación. El valor predeterminado es 4, lo que significa 16 bytes. Si lo establece en 3 (es decir, 8 bytes), la asignación de la pila (sub
yadd
pararsp
) desaparece del código de ensamblaje generado.Echa un vistazo a godbolt .
fuente