Warum kennt der Compiler die Adressen lokaler Variablen zur Kompilierzeit nicht?

8

Was bedeutet die folgende Aussage?

  

Lokale und dynamisch zugewiesene Variablen haben Adressen, die dem Compiler beim Kompilieren der Quelldatei nicht bekannt sind

Früher dachte ich, dass lokale Variablen zur Kompilierzeit Adressen zugewiesen werden, aber diese Adresse kann sich ändern, wenn sie außerhalb des Gültigkeitsbereichs liegt und dann beim Funktionsaufruf wieder in den Gültigkeitsbereich fällt. Aber die obige Aussage besagt, dass Adressen von lokalen Variablen dem Compiler nicht bekannt sind. Wie werden dann lokale Variablen zugewiesen? Warum können globale Variablenadressen zur Kompilierzeit bekannt sein?

Können Sie bitte auch einen guten Link bereitstellen, um zu lesen, wie lokale Variablen und andere zugewiesen sind?

Vielen Dank im Voraus!

    
T.J. 08.02.2012, 02:50
quelle

4 Antworten

13

Das obige Zitat ist korrekt - der Compiler kennt die Adresse der lokalen Variablen normalerweise nicht zur Kompilierzeit. Das heißt, der Compiler kennt wahrscheinlich den Offset von der Basis des Stack-Frames, an dem sich eine lokale Variable befindet, aber abhängig von der Tiefe des Aufruf-Stacks, der sich zur Laufzeit in eine andere Adresse übersetzen lässt. Betrachten Sie als Beispiel diesen rekursiven Code (der übrigens kein guter Code ist!):

%Vor%

Je nach dem Parameter num könnte dieser Code mehrere rekursive Aufrufe ergeben, so dass es mehrere Kopien von result im Speicher gibt, die jeweils einen anderen Wert haben. Folglich kann der Compiler nicht wissen, wohin sie alle gehen werden. Allerdings wird jede Instanz von result wahrscheinlich um die gleiche Menge von der Basis des Stack-Rahmens versetzt, der jeden Factorial Aufruf enthält, obwohl der Compiler theoretisch andere Dinge wie die Optimierung dieses Codes tun könnte, so dass es nur eine Kopie von gibt result .

In der Regel weisen Compiler lokale Variablen zu, indem sie ein Modell des Stack-Frames beibehalten und verfolgen, wo sich die nächste freie Position im Stack-Frame befindet. Auf diese Weise können lokale Variablen relativ zu dem Start des Stapelrahmens zugeordnet werden, und wenn die Funktion aufgerufen wird, kann diese relative Adresse in Verbindung mit der Stapeladresse verwendet werden, um den Ort dieser Variablen in dem bestimmten Stapelrahmen nachzuschlagen .

Auf der anderen Seite können globale Variablen ihre Adressen zur Kompilierungszeit haben. Sie unterscheiden sich von Einheimischen hauptsächlich dadurch, dass es immer eine Kopie einer globalen Variablen in einem Programm gibt. Abhängig davon, wie die Ausführung abläuft, können lokale Variablen 0 oder öfter vorkommen. Aufgrund der Tatsache, dass es eine eindeutige Kopie des globalen gibt, kann der Compiler eine Adresse dafür fest codieren.

Wenn Sie sich weitergehend damit befassen möchten, wie ein Compiler Variablen auslegen kann, sollten Sie sich eine Kopie von Compiler: Prinzipien, Techniken und Werkzeuge, Zweite Ausgabe von Aho, Lam, Sethi und Ullman. Obwohl ein großer Teil dieses Buches andere Compiler-Konstruktionstechniken betrifft, widmet sich ein großer Teil des Buches der Implementierung der Codegenerierung und den Optimierungen, die zur Verbesserung des generierten Codes verwendet werden können.

Hoffe, das hilft!

    
templatetypedef 08.02.2012, 02:53
quelle
1

Meiner Meinung nach bezieht sich die Aussage nicht auf den Laufzeitzugriff auf Variablen oder das Scoping, sondern versucht etwas subtileres zu sagen.

Der Schlüssel hier ist, dass seine "lokale und dynamisch zugewiesene" und "Kompilierzeit". Ich glaube, was die Aussage sagt, ist, dass diese Adressen nicht als Kompilierzeitkonstanten verwendet werden können. Dies steht im Gegensatz zu der Adresse von statisch zugewiesenen Variablen, die als Kompilierzeitkonstanten verwendet werden können. Ein Beispiel dafür sind Vorlagen:

%Vor%

Es scheint einige Einschränkungen für Vorlagen zu geben, die das nicht erlauben:

%Vor%

Andere Kontexte, die Kompilierzeitkonstanten verwenden, können jedoch &y verwenden.

Und ähnlich würde ich erwarten, dass dies ungültig ist:

%Vor%

Da ps Daten jetzt dynamisch zugewiesen sind (obwohl p statisch ist).

    
Michael Anderson 08.02.2012 03:10
quelle
0
  1. Adresse der dynamischen Variablen sind nicht für den erwarteten Grund bekannt, da sie dynamisch aus dem Speicherpool zugewiesen werden.
  2. Adresse von lokalen Variablen sind nicht bekannt, weil sie sich auf befinden Speicherbereich "stapeln". Stack-Wickeln-Abwickeln eines Programms kann basierend auf Laufzeitbedingungen des Code-Flusses verzögern.

Zum Beispiel:

%Vor%

Die Bedingung if kann true oder false sein und das Ergebnis ist nur zur Laufzeit bekannt. Basierend darauf würde int i oder int j bei entsprechendem Offset auf Stack stattfinden.

    
iammilind 08.02.2012 02:53
quelle
0

Es ist eine nette Frage.

Während der Code ausgeführt wird, wird das Programm in den Speicher geladen. Dann erhält die lokale Variable die Adresse. Zur Kompilierungszeit wird der Quellcode in den Maschinensprachencode konvertiert, so dass er ausgeführt werden kann.

    
user966379 08.02.2012 05:27
quelle

Tags und Links