2014-04-25 11 views
6

Ich versuche, den Stapelrahmen in C zu verstehen, also schrieb ich einen einfachen C-Code, um den Stapelrahmen zu analysieren.Stapelrahmen in C verstehen

  • Zunächst wird der fun1() gibt eine Adresse einer lokalen Variablen, die auf 10 initialisiert wird ptr was zu einer Warnung führt, aber das ist ok ... Wenn ich den Wert von * ptr drucken jetzt druckt 10, auch das ist in Ordnung ...

  • Nächste fun2() gibt eine Adresse einer lokalen Variablen, die nicht einmal initialisiert ist und wenn ich versuche, den Wert von * ptr jetzt 10 Drucke egal ob ich bin Eine Adresse von a oder b zurücksenden ...

  • Um zu verstehen, was hier eigentlich passiert, habe ich gdb benutzt. GDB, begann ich Schritt für Schritt das Debuggen und wenn ich die Zeile erreicht „Rückkehr & ein“ in fun2(), habe ich versucht Adresse von b zu drucken, Druck & b aber es gedruckt Can not Nimm die Adresse von "b", was kein Lvalue ist.

Ich verstehe nicht, wenn ich versuche, um die Adresse eines zu drucken, Druck & ein druckt es absolut in Ordnung, warum dann nicht von B-Adresse. * Warum ist b nicht ein Wert, wenn ein ist?

# include <stdio.h> 

int * fun1() { 
    int a = 10; 
    return &a; 
} 

int * fun2() 
{ 
    int a; 
    int b; 
    return &a;   // return &b; 
} 

int main() 
{ 
    int *ptr; 
    ptr = fun1(); 
    ptr = fun2(); 
    printf ("*ptr = %d, fun2() called...\n", *ptr); 
    return 0; 
} 
+0

http://stackoverflow.com/a/18479996/1814023 –

+1

Sie sind nicht definiertes Verhalten aufrufen. Es gibt keine Garantie, dass die Ergebnisse Sinn machen oder das tun, was Sie vom Stack-Layout erwarten würden. Die Standard-Übertreibung ist, dass das Programm erlaubt wird, [Dämonen] (http://www.catb.org/jargon/html/N/nasal-demons.html) aus der Nase fliegen zu lassen. – user2357112

+2

Du hast Glück, dass der Ausdruck '* ptr'10 druckt; es ist sicherlich nicht garantiert, dies zu tun (Sie rufen unbestimmtes Verhalten auf). Aber du solltest wirklich den ganzen Code zeigen. Im Code hat der Compiler wahrscheinlich "b" als eine nicht verwendete Variable fallen gelassen, so dass er keinen Speicherort hat. Daher können Sie seine Adresse nicht verwenden. Verwenden Sie "b" im Code, und Sie können es ausdrucken. Und bitte, melde nichts "wie"; genau sein und genau berichten, was der Debugger sagt. –

Antwort

3

Der Compiler optimiert einige Code in fun2.

Wenn Sie &a zurückgeben, wird int b; entfernt. Wenn Sie &b zurückgeben, wird int a; optimiert. Wenn Sie Dummy-Berechnungen hinzufügen, sehen Sie, dass die Adressen der zurückgegebenen Werte unterschiedlich sind.

int * fun2() 
{ 
    int a; 
    int b; 
    int* p = &a; 
    p = &b; 
    return p; 
} 

ändern main die zurückgegebenen Werte von fun1 und fun2 zu drucken.

int main() 
{ 
    int *ptr; 
    ptr = fun1(); 
    printf ("ptr = %p, fun1() called...\n", ptr); 
    ptr = fun2(); 
    printf ("ptr = %p, fun2() called...\n", ptr); 
    printf ("*ptr = %d, fun2() called...\n", *ptr); 
    return 0; 
} 

Wenn ich diesen Code ausführen, bekomme ich die folgende Beispielausgabe:

 
ptr = 0x7ffff98c70ec, fun1() called... 
ptr = 0x7ffff98c70e4, fun2() called... 
*ptr = 32749, fun2() called... 
+0

Ja das ist true, wenn ich b initialisiere, gibt es einen Müll zurück, aber das selbe sollte wahr sein, wenn ich mit dem -O0 Level der Optimierung kompiliere. Aber wenn ich es mit dem -O-Level der Optimierung kompiliere, ist das Ergebnis wieder dasselbe, d. H. 10 – Adarsh

0

Es ist für mich kompiliert nur gut, wenn die Adresse der Rückkehr zu b. Aber Sie sollten nicht die Adresse einer lokalen Variablen zurückgeben. Check out this link.

+0

Ja, das ist wahr, aber mein Ziel ist hier nichts aus diesem Code zu erreichen, sondern zu verstehen, wie die in einer Funktion verwendete Adresse der Stapelvariablen in einer anderen Funktion wiederverwendet werden kann ... Danke für die Hilfe ... – Adarsh