Betrachten Sie das folgende Beispiel:
struct vector {
int size() const;
bool empty() const;
};
bool vector::empty() const
{
return size() == 0;
}
Der generierte Assemblycode für vector::empty
(durch Klirren, mit Optimierungen):
push rax
call vector::size() const
test eax, eax
sete al
pop rcx
ret
Warum wird Stapelspeicher zugewiesen? Es wird überhaupt nicht verwendet. Das push
und pop
könnte weggelassen werden. Optimierte Builds von MSVC und gcc verwenden für diese Funktion auch Stapelspeicher (siehe Godbolt ), daher muss es einen Grund geben.
this
Parameter berücksichtigt ?vector::size()
wird im Beispiel nicht definiert, um zu simulieren, dass es nicht inline ist.vector::size()
nicht relevant für das Zuweisen oder Nichtzuweisen eines Stapelrahmens für istvector::empty()
. Darinempty()
heißt es einfach, was auch immer es ist.Antworten:
Es weist Stapelspeicherplatz zu, sodass der Stapel 16-Byte-ausgerichtet ist. Dies ist erforderlich, da die Rücksprungadresse 8 Byte benötigt. Daher wird ein zusätzlicher 8-Byte-Speicherplatz benötigt, um den Stapel mit 16 Byte ausgerichtet zu halten.
Die Ausrichtung von Stapelrahmen kann für einige Compiler mit Befehlszeilenargumenten konfiguriert werden.
rsp
zu Beginn der Funktion werden, was bedeutet, dass dies auch von etwas anderem beeinflusst wird.-mstack-alignment
Option gibt die Stapelausrichtung an. Es scheint, dass der Standardwert 16 ist, obwohl er nicht dokumentiert ist. Wenn Sie 8 festlegen, wird die Stapelzuordnung (push
undpop
) aus dem generierten Assemblycode entfernt.-mpreferred-stack-boundary
Option gibt die Stapelausrichtung an. Wenn der angegebene Wert N ist, bedeutet dies 2 ^ N Bytes Ausrichtung. Der Standardwert ist 4, was 16 Bytes bedeutet. Wenn Sie 3 (dh 8 Byte) festlegen, verschwindet die Stapelzuordnung (sub
undadd
fürrsp
) aus dem generierten Assemblycode.Schauen Sie sich Godbolt an .
quelle