Wie genau ist der callstack Arbeit?

Ich versuche, ein tieferes Verständnis darüber, wie die low-level-Operationen von Programmiersprachen zu arbeiten und vor allem, wie Sie interagieren mit der OS/CPU. Ich habe wohl gelesen, jede Antwort in jedem stack - /heap-bezogenen thread hier auf Stack Überlauf, und Sie sind alle genial. Aber es gibt noch eine Sache, die ich nicht ganz verstehen aber.

Betrachten Sie diese Funktion in pseudo-code, die dazu neigt, um gültig zu sein Rost-code; -)

fn foo() {
    let a = 1;
    let b = 2;
    let c = 3;
    let d = 4;

    //line X

    doSomething(a, b);
    doAnotherThing(c, d);
}

Dies ist, wie ich annehme, den Stapel zu schauen, wie in Zeile X:

Stack

a +-------------+
  | 1           | 
b +-------------+     
  | 2           |  
c +-------------+
  | 3           | 
d +-------------+     
  | 4           | 
  +-------------+ 

Nun, alles, was ich gelesen habe darüber, wie der stack funktioniert, ist, dass es strikt befolgt LIFO-Regeln (last in, first out). Genau wie ein stack-Datentyp in .NET, Java oder jede andere Programmiersprache.

Aber wenn das der Fall ist, dann was passiert nach der Linie X? Denn natürlich, das nächste, was wir brauchen, ist die Arbeit mit a und b, aber das würde bedeuten, dass die OS/CPU (?) hat, um pop-out d und c erste, um wieder zu a und b. Aber dann wäre es zu Schießen selbst in den Fuß, da braucht es c und d in die nächste Zeile.

So, ich Frage mich, was genau passiert hinter den kulissen?

Andere Frage. Betrachten wir übergeben Sie einen Verweis auf eine der anderen Funktionen wie diese:

fn foo() {
    let a = 1;
    let b = 2;
    let c = 3;
    let d = 4;

    //line X

    doSomething(&a, &b);
    doAnotherThing(c, d);
}

So, wie ich die Dinge verstehen, würde dies bedeuten, dass die Parameter in doSomething sind im wesentlichen auf das gleiche Speicheradresse wie a und b im foo. Aber dann wieder das bedeutet, dass es keine pop in den stack, bis wir a und b passiert.

Diese beiden Fälle machen mich denken, dass ich noch nicht vollständig Begriffen, wie genau der stack funktioniert und wie folgt strikt der LIFO Regeln.

LIFO nur Angelegenheiten, die für die Reservierung von Speicherplatz auf dem stack. Sie können immer Zugriff auf alle Variablen, die mindestens auf Ihrer stack-frame (innerhalb der Funktion deklariert) auch wenn es unter einer Menge von anderen Variablen
In anderen Worten, LIFO bedeutet, dass Sie können hinzufügen oder entfernen von Elementen nur am Ende der Stapel, und man kann immer Lesen/ändern element.
Warum gehst du nicht zerlegen einer einfachen Funktion nach dem kompilieren mit -O0 und Blick auf die generierten Anweisungen? Es ist ziemlich, naja, aufschlussreich ;-). Finden Sie, dass der code macht guten Gebrauch von der R-Teil des RAM; es greift auf die Adressen direkt auf wird. Sie können denken, der den Namen einer Variablen als offset zur Adresse register (stack-pointer). Wie die anderen gesagt haben, ist der Stapel nur LIFO-mit Bezug auf das stapeln (gut für die Rekursion etc.). Es ist nicht LIFO-mit Bezug auf auf es zu. Der Zugang ist völlig zufällig.
Sie können Ihre eigenen stack-Datenstruktur mit einem array, und nur die Speicherung der index des obersten Elements, erhöht, wenn Sie drücken, Dekrementieren, wenn Sie pop. Wenn Sie dies getan haben, würden Sie immer noch Zugriff auf jedes einzelne element im array zu jeder Zeit, ohne drücken oder knallen, wie Sie können immer mit arrays. Ungefähr das gleiche ist hier passiert.
Im Grunde ist die Benennung stack/heap ist bedauerlich. Sie tragen wenig ähnlichkeit mit der stack-und heap-Datenstrukturen' Terminologie, so nannte Sie die gleiche ist, ist sehr verwirrend.

InformationsquelleAutor Christoph | 2014-06-01

Schreibe einen Kommentar