Ein Stapelrahmen ist ein Datenrahmen, der auf den Stapel verschoben wird. Im Fall eines Aufrufstapels würde ein Stapelrahmen einen Funktionsaufruf und seine Argumentdaten darstellen.
Wenn ich mich richtig erinnere, wird zuerst die Funktionsrückgabeadresse auf den Stapel verschoben, dann die Argumente und der Platz für lokale Variablen. Zusammen bilden sie den "Rahmen", obwohl dies wahrscheinlich architekturabhängig ist. Der Prozessor weiß, wie viele Bytes sich in jedem Frame befinden, und bewegt den Stapelzeiger entsprechend, wenn Frames vom Stapel verschoben und entfernt werden.
BEARBEITEN:
Es gibt einen großen Unterschied zwischen übergeordneten Call-Stacks und dem Call-Stack des Prozessors.
Wenn wir über den Aufrufstapel eines Prozessors sprechen, sprechen wir über das Arbeiten mit Adressen und Werten auf Byte- / Wortebene im Assembly- oder Maschinencode. Es gibt "Aufrufstapel", wenn es um übergeordnete Sprachen geht, aber sie sind ein Debugging- / Laufzeit-Tool, das von der Laufzeitumgebung verwaltet wird, damit Sie protokollieren können, was mit Ihrem Programm schief gelaufen ist (auf hoher Ebene). Auf dieser Ebene sind häufig Zeilennummern sowie Methoden- und Klassennamen bekannt. Bis der Prozessor den Code erhält, hat er absolut kein Konzept für diese Dinge.
Wenn Sie Stack sehr gut verstehen, werden Sie verstehen, wie Speicher im Programm funktioniert, und wenn Sie verstehen, wie Speicher im Programm funktioniert, werden Sie verstehen, wie Funktionsspeicher im Programm gespeichert sind, und wenn Sie verstehen, wie Funktionsspeicher im Programm funktionieren, werden Sie verstehen, wie rekursive Funktionen funktionieren und wenn Sie verstehen, wie die rekursive Funktion funktioniert. Sie werden verstehen, wie der Compiler funktioniert. Wenn Sie verstehen, wie der Compiler funktioniert, funktioniert Ihr Verstand als Compiler und Sie können jedes Programm sehr einfach debuggen
Lassen Sie mich erklären, wie Stack funktioniert:
Zuerst müssen Sie wissen, wie Funktionen im Stapel dargestellt werden:
Heap speichert dynamisch zugewiesene Werte.
Der Stapel speichert automatische Zuordnungs- und Löschwerte.
Lassen Sie uns mit Beispiel verstehen:
Verstehen Sie nun Teile dieses Programms:
Nun wollen wir sehen, was Stapel ist und was Stapelteile sind:
Denken Sie an eines: Wenn die Rückgabebedingung einer Funktion erfüllt ist, unabhängig davon, ob sie die lokalen Variablen geladen hat oder nicht, kehrt sie sofort mit ihrem Stapelrahmen vom Stapel zurück. Dies bedeutet, dass die Basisbedingung nicht darauf wartet, lokale Variablen zu laden, die sich im Teil "else" des Programms befinden, wenn eine rekursive Funktion die Basisbedingung erfüllt und wir eine Rückgabe nach der Basisbedingung setzen. Der aktuelle Frame wird sofort vom Stapel zurückgegeben, woraufhin sich der nächste Frame im Aktivierungsdatensatz befindet.
Sehen Sie dies in der Praxis:
Immer wenn eine Funktion auf eine return-Anweisung stößt, wird der aktuelle Frame vom Stapel gelöscht.
Bei der Rückkehr vom Stapel werden die Werte in umgekehrter Reihenfolge zurückgegeben, in der sie ursprünglich im Stapel zugewiesen wurden.
quelle
hello()
rekursiv aufgerufen wurde,hello()
was dann (wieder) rekursiv aufgerufen wurdehello()
, und der globale Rahmen ist die ursprüngliche Funktion, die den ersten aufgerufen hathello()
?Ein kurzer Abschluss. Vielleicht hat jemand eine bessere Erklärung.
Ein Aufrufstapel besteht aus 1 oder mehreren mehreren Stapelrahmen. Jeder Stapelrahmen entspricht einem Aufruf einer Funktion oder Prozedur, die noch nicht mit einer Rückgabe beendet wurde.
Um einen Stapelrahmen zu verwenden, behält ein Thread zwei Zeiger bei, von denen einer als Stapelzeiger (SP) und der andere als Rahmenzeiger (FP) bezeichnet wird. SP zeigt immer auf die "Oberseite" des Stapels und FP zeigt immer auf die "Oberseite" des Rahmens. Zusätzlich verwaltet der Thread einen Programmzähler (PC), der auf den nächsten auszuführenden Befehl zeigt.
Auf dem Stapel werden folgende Daten gespeichert: lokale Variablen und Provisorien, tatsächliche Parameter der aktuellen Anweisung (Prozedur, Funktion usw.)
Es gibt verschiedene Aufrufkonventionen bezüglich der Reinigung des Stapels.
quelle
"Ein Aufrufstapel besteht aus Stapelrahmen ..." - Wikipedia
Ein Stapelrahmen ist eine Sache, die Sie auf den Stapel legen. Dies sind Datenstrukturen, die Informationen zu aufzurufenden Unterprogrammen enthalten.
quelle
Programmierer haben möglicherweise Fragen zu Stapelrahmen nicht in einem weiten Sinne (dass es sich um eine einzelne Entität im Stapel handelt, die nur einen Funktionsaufruf bedient und die Rücksprungadresse, Argumente und lokalen Variablen beibehält), sondern im engeren Sinne - wenn der Begriff
stack frames
in erwähnt wird Kontext der Compileroptionen.Ob der Autor der Frage es gemeint hat oder nicht, aber das Konzept eines Stapelrahmens unter dem Aspekt der Compileroptionen ist ein sehr wichtiges Thema, das in den anderen Antworten hier nicht behandelt wird.
Der Microsoft Visual Studio 2015 C / C ++ - Compiler verfügt beispielsweise über die folgende Option
stack frames
:GCC haben Folgendes:
Intel C ++ Compiler haben Folgendes:
welches den folgenden Alias hat:
Delphi verfügt über die folgende Befehlszeilenoption:
In diesem speziellen Sinne ist aus Sicht des Compilers ein Stapelrahmen nur der Eingangs- und Ausgangscode für die Routine , der einen Anker auf den Stapel schiebt - der auch zum Debuggen und zur Ausnahmebehandlung verwendet werden kann. Debugging-Tools können die Stapeldaten scannen und diese Anker zum Zurückverfolgen verwenden, während sie sich
call sites
im Stapel befinden, dh um die Namen der Funktionen in der Reihenfolge anzuzeigen, in der sie hierarchisch aufgerufen wurden. Für die Intel-Architektur ist espush ebp; mov ebp, esp
oderenter
für den Ein- und /mov esp, ebp; pop ebp
oderleave
Ausstieg.Aus diesem Grund ist es für einen Programmierer sehr wichtig zu verstehen, in welchem Stapelrahmen sich die Compileroptionen befinden, da der Compiler steuern kann, ob dieser Code generiert werden soll oder nicht.
In einigen Fällen kann der Compiler auf den Stapelrahmen (Eingangs- und Ausgangscode für die Routine) verzichten, und auf die Variablen wird direkt über den Stapelzeiger (SP / ESP / RSP) und nicht über den praktischen Basiszeiger (BP /) zugegriffen. ESP / RSP). Bedingungen für das Weglassen des Stapelrahmens, zum Beispiel:
Das Weglassen von Stapelrahmen (Eingabe- und Ausstiegscode für die Routine) kann den Code kleiner und schneller machen, kann jedoch auch die Fähigkeit der Debugger beeinträchtigen, die Daten im Stapel zurückzuverfolgen und dem Programmierer anzuzeigen. Dies sind die Compileroptionen, die bestimmen, unter welchen Bedingungen eine Funktion den Eingangs- und Ausgangscode haben soll, zum Beispiel: (a) immer, (b) nie, (c) bei Bedarf (Angabe der Bedingungen).
quelle
Der Stapelrahmen ist die gepackte Information, die sich auf einen Funktionsaufruf bezieht. Diese Informationen enthalten im Allgemeinen Argumente, die an die Funktion übergeben werden, lokale Variablen und die Rückgabe beim Beenden. Aktivierungsdatensatz ist ein anderer Name für einen Stapelrahmen. Das Layout des Stapelrahmens wird im ABI vom Hersteller festgelegt, und jeder Compiler, der die ISA unterstützt, muss diesem Standard entsprechen. Das Layoutschema kann jedoch vom Compiler abhängig sein. Im Allgemeinen ist die Stapelrahmengröße nicht begrenzt, aber es gibt ein Konzept namens "rote / geschützte Zone", mit dem Systemaufrufe usw. ausgeführt werden können, ohne einen Stapelrahmen zu stören.
Es gibt immer einen SP, aber bei einigen ABIs (z. B. ARMs und PowerPCs) ist FP optional. Argumente, die auf den Stapel gelegt werden mussten, können nur mit dem SP ausgeglichen werden. Ob ein Stapelrahmen für einen Funktionsaufruf generiert wird oder nicht, hängt von der Art und Anzahl der Argumente, den lokalen Variablen und dem allgemeinen Zugriff auf lokale Variablen ab. Bei den meisten ISAs werden zunächst Register verwendet. Wenn mehr Argumente als Register zum Übergeben von Argumenten vorhanden sind, werden diese auf den Stapel gelegt (z. B. verfügt x86 ABI über 6 Register zum Übergeben ganzzahliger Argumente). Daher benötigen einige Funktionen manchmal keinen Stapelrahmen, um auf dem Stapel platziert zu werden, sondern nur die Rücksprungadresse wird auf den Stapel verschoben.
quelle