2012-09-13 41 views
0

可能重复:
Can a local variable's memory be accessed outside its scope?返回的局部变量的行为的地址

输入:

#include <stdlib.h> 
#include <stdio.h> 
int func2(void); 
int* func1(void); 

int func2(void) 
{ 
    int* b; 
    b = func1(); 
    printf("%d", *b); 
    printf("%d", *b); 
    printf("%d", *b); 
} 

int* func1() 
{ 
    int a = 13; 
    return &a; 
} 

int main() 
{ 
    func2(); 
} 

输出:

13 -1077824828 -1077824828 

有人可以解释堆栈和操作系统中发生了什么?为什么在得到指针的值后结果从13变为垃圾?

+4

重复数字无限加1。这是未定义的行为。 –

+0

此外,'func2'不返回任何东西,尽管它的返回类型为int。 –

+0

要真正回答这个问题:在你的特定情况下,第一次调用'printf()'覆盖从调用到'func1()'时堆栈剩余的'13'。 – Mysticial

回答

1

当然。 调试和发布(清理)结果不同。 如果您查看程序集,则局部变量是EBP-(某些偏移量)。 这意味着更高层叠,如“更远”。

这是您返回的地址。

通常情况下,如果函数返回就不会触动。在某些编译器的调试版本中,它会被有意识地删除,以帮助您更快地捕获悬挂指针错误。现在,printf调用重用堆栈中的相同地址来传递参数和自己的局部变量(它有一些)。它们将被写入到由func1 return清空的地址,从而覆盖您获得的地址指向的任何地址。

+0

为什么printf会将参数传递给堆栈?他们不是直接发送到标准输出缓冲区吗? – Nizarazo

+0

不,它们很重要:生成调用者代码的编译器不知道“printf”是什么意思,特别是这个函数要做什么 - 比如使用stdout。 –

1

调用printf创建一个新的堆栈框架,覆盖之前由a占用的位置。

+1

也许,或者不是。你不能真正推理一下当你调用未定义的行为时会发生什么。 –

+0

当然可以。迪马是对的。它是完美定义的,但依赖于平台。 –

相关问题