2010-12-13 4 views
2

Dies wurde für eine lange Zeit stört mich jetzt: Können sagen, ich habe eine Funktion:C++: Funktionsvariable Deklarationen, wie funktioniert es intern?

void test(){ 
    int t1, t2, t3; 
    int t4 = 0; 
    int bigvar[10000]; 
    // do something 
} 

Wie geht der Computer die Speicherzuordnungen für die Variablen?

Ich dachte immer, dass der Variablenraum in der .exe gespeichert wird, die der Computer dann lesen wird, ist das korrekt? Aber soweit ich weiß, die Array nicht 10000 int Elemente Platz in der .exe, seit seiner nicht initialisierten. Wie funktioniert die Speicherzuordnung, wenn ich die Funktion aufruft?

+0

Die EXE wird in einer _disk_ gespeichert und der kompilierte Code wird dort gespeichert. Aber wenn es ausgeführt wird, nimmt es Speicher von der Einheit _processor_. Bytes in der Festplatte entsprechen nicht den Bytes, die für Variablen benötigt werden. –

+0

http://stackoverflow.com/questions/556714/how-does-the-stack-work-in-assembly-language – karlphillip

Antwort

9

Lokale Variablen wie diese werden normalerweise mit dem Prozessor stack implementiert. Das bedeutet, dass der Compiler nur die Größe jeder Variablen berechnen und sie addieren muss. Die Gesamtsumme ist der Betrag, um den der Stapelzeiger beim Eintritt in die Funktion geändert wird, und beim Verlassen zurück zu wechseln. Auf jede Variable wird dann mit ihrem relativen Versatz in diesen Speicherblock auf dem Stapel zugegriffen.

Ihr Code, wenn in Linux kompiliert, wie dies in x86-Assembler suchen endet:

test: 
     pushl %ebp 
     movl %esp, %ebp 
     subl $40016, %esp 
     movl $0, -4(%ebp) 
     leave 
     ret 

In der oben die Konstante 40016 $ der Raum für die vier 32-Bit ints t1, t2, t3 und t4 erforderlich ist, während die verbleibenden 40000 Byte für das Array mit 10000 Elementen verantwortlich sind.

+0

nette Erklärung! – Nawaz

0

Ich kann nicht viel zu dem, was bereits gesagt wurde, außer ein paar Notizen hinzufügen. Sie können lokale Variablen tatsächlich in eine ausführbare Datei einfügen und sie im Datensegment (und initialisiert) anstelle des Stapelsegments zuweisen. Um dies zu tun, deklarieren Sie sie als static. Aber dann würden alle Aufrufe der Funktion die gleichen Variablen teilen, während im Stapel jeder Aufruf eine neue Gruppe von Variablen erzeugt. Dies kann zu vielen Problemen führen, wenn die Funktion gleichzeitig von mehreren Threads aufgerufen wird oder wenn es eine Rekursion gibt (versuchen Sie sich das vorzustellen). Aus diesem Grund verwenden die meisten Sprachen den Stack für lokale Variablen und static wird selten verwendet.

0

Auf einigen alten Compilern, ich habe das Verhalten erfüllt, dass das Array statisch zugewiesen ist. Das bedeutet, dass es Speicher dafür reserviert, wenn es das Programm lädt, und diesen Speicherplatz anschließend verwendet. Dieses Verhalten ist nicht sicher (siehe Sergey's Antwort), noch erwarte ich, dass es gemäß den Standards erlaubt ist, aber ich habe es in freier Wildbahn angetroffen. (Ich habe keine Erinnerung an, welcher Compiler es war.)

Zum größten Teil werden lokale Variablen auf dem Stapel zusammen mit Rückkehradressen und all diesen anderen Sachen gehalten. Dies bedeutet, dass die nicht initialisierten Werte möglicherweise vertrauliche Informationen enthalten. Dazu gehören auch Arrays, wie in der Antwort von Unwind.

Eine andere gültige Implementierung ist, dass die Variable, die auf dem Stapel gefunden wird, ein Zeiger ist und dass der Compiler die Zuordnung und Freigabe (vermutlich in einer Ausnahme-sicheren Weise) unter der Haube ausführt. Dies spart Stapelspeicherplatz (der vor dem Programmstart zugewiesen werden muss und nicht einfach für x86-Architekturen erweitert werden kann) und ist auch sehr nützlich für C-Standard-VLA (Array variabler Länge, alias arum mans std :: vector)