Prenons l'exemple suivant:
struct vector {
int size() const;
bool empty() const;
};
bool vector::empty() const
{
return size() == 0;
}
Le code d'assembly généré pour vector::empty
(par clang, avec optimisations):
push rax
call vector::size() const
test eax, eax
sete al
pop rcx
ret
Pourquoi alloue-t-il de l'espace de pile? Il n'est pas utilisé du tout. Le push
et pop
pourrait être omis. Les versions optimisées de MSVC et gcc utilisent également l'espace de pile pour cette fonction (voir sur godbolt ), donc il doit y avoir une raison.
this
paramètre implicite ?vector::size()
n'est pas défini dans l'exemple pour simuler qu'il n'est pas en ligne.vector::size()
n'est pas pertinent pour allouer ou ne pas allouer un cadre de pile pourvector::empty()
. Enempty()
elle est simplement appelée, quelle qu'elle soit.Réponses:
Il alloue l'espace de pile, donc la pile est alignée sur 16 octets. Il est nécessaire, car l'adresse de retour prend 8 octets, donc un espace supplémentaire de 8 octets est nécessaire pour garder la pile de 16 octets alignée.
L'alignement des cadres de pile peut être configuré avec des arguments de ligne de commande pour certains compilateurs.
rsp
au début de la fonction, ce qui signifie que quelque chose d'autre affecte également cela.-mstack-alignment
option spécifie l'alignement de la pile. Il semble que la valeur par défaut soit 16, bien que non documentée. Si vous le définissez sur 8, l'allocation de pile (push
etpop
) disparaît du code d'assembly généré.-mpreferred-stack-boundary
option spécifie l'alignement de la pile. Si la valeur donnée est N, cela signifie 2 ^ N octets d'alignement. La valeur par défaut est 4, ce qui signifie 16 octets. Si vous le définissez sur 3 (c'est-à-dire 8 octets), l'allocation de pile (sub
etadd
pourrsp
) disparaît du code d'assembly généré.Découvrez Godbolt .
la source