2014-04-25 52 views
6

我想了解C中的堆栈帧,因此我编写了一个简单的C代码来分析堆栈帧。了解堆栈帧C

  • 首先在FUN1的()返回一个被初始化为10到PTR这导致了警告,但没关系......如果我现在打印* PTR的值,它打印的局部变量的地址10,即使这没关系...

  • 接下来fun2()返回一个局部变量的地址,它甚至没有被初始化,如果我尝试打印* ptr的值,现在它打印10,无论我是否返回a或b的地址...

  • 要理解这里实际发生的事情,我使用了gdb。用gdb ,我开始一步一步的调试,当我到达行“回&一个”在FUN2(),我试图打印B的地址,打印& b但它印 无法采取不是左值的“b”的地址。

,当我尝试打印的地址我不明白,打印&一个它打印精美绝伦,那么为什么不解决B的。 * a为什么不是一个左值?

# 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

你调用未定义的行为。不能保证结果会有任何意义或做到您期望的堆栈布局。标准的夸张之处在于,该程序允许[恶魔](http://www.catb.org/jargon/html/N/nasal-demons.html)飞出你的鼻子。 – user2357112

+2

很幸运,打印'* ptr'打印10;它肯定不能保证这么做(你正在调用未定义的行为)。但你真的应该显示所有的代码。在代码中,编译器可能会将'b'作为一个未使用的变量,因此它没有位置,因此您无法获取它的地址。以某种方式在代码中使用'b',你就可以打印出来。请不要报告“类似的东西”;确切地说,并且准确地报告调试器说的内容。 –

回答

3

编译器正在优化掉fun2中的一些代码。

如果您返回&a,它将优化为int b;。如果您返回&b,它将优化离开int a;。如果您添加一些虚拟计算,您将看到返回值的地址将会不同。

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

变化main打印的fun1fun2返回值。

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; 
} 

当我运行这段代码,我得到下面的示例输出:

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

雅这就是如果我初始化b,则返回true,如果我使用-O0优化级别进行编译,则返回垃圾,但同样如此。但是,当我用-O0优化级别进行编译时,结果再次相同,即10 – Adarsh

0

它返回到B的地址时,编译对我就好了。但是你不应该返回一个局部变量的地址。 Check out this link

+0

雅这是真的,但我的目标是不从这个代码完成任何事情,但了解如何在一个函数中使用堆栈变量的地址可以在另一个函数中重新使用...感谢您的帮助... – Adarsh