2014-01-09 65 views
1

在我看来,块中的自动变量在跳转到外部作用域后会被释放。然后我写了一个程序来测试这个,令我惊讶的是,它运行正常。它甚至跑了好几次。从块外部访问块内的自动变量的内存?

的程序是:

#include <stdio.h> 

int main(int argc, char **argv) 
{ 
    int *a = 0; 

    { 
     int b = 2; 
     a = &b; 
    } 

    printf("%d\n", *a); 
    return 0; 
} 

打印结果是2,怎么会出现这种情况?

+1

该内存仍然存在,它只会被下一个函数调用或块范围破坏。它就像在释放堆分配块之后从内存中读取数据一样。你不能指望它的工作,但有时它确实。 – woolstar

+1

简单,你很幸运。内存被标记为“空闲”,但不会“释放”,因为除非有人要求,否则不需要这样做。 –

+1

就像这个人住在地板上给你一台电脑,即使那个人搬出去了,你家里仍然有电脑 – Rugal

回答

2

根据ANSI标准,块外自动变量'b'的任何引用都是无效的。它取决于编译器,它们如何在栈帧上推送和弹出本地变量。当它从最外面的块中退出时,编译器可能会弹出所有的本地文件。

即使不在堆栈上,也可以读取地址。如果堆栈进一步增长,该地址可能会被其他变量修改。在这种情况下,您将无法再次读取相同的数据。

+0

我的编译器是gcc 4.4.7。你的意思是,如果编译器在内部块结束后弹出自动变量,那么以前的内存将被新的自动变量覆盖?例如,如果我添加语句后的语句:int c = 3,那么它会打印:3以外的2? – ray5

+0

是的,但它可能是从最外面块中退出时弹出所有局部变量的情况。你可以编写一个小程序来知道它是如何推送和弹出局部变量的? – iGRJ

0

自动变量的范围可分为以下几类:

  1. 全球范围
  2. 功能范围
  3. 区块范围

依赖于它的声明,它可以有不同的“可见度”。

在您的代码中,变量“b”仅在其范围内可见。它可以分配内存并可以在该范围内使用。在外部时,该内存不再与变量“b”相关联。

但是,这并不意味着它被释放。如果你声明另一个变量或块,它可能使用相同的内存位置。

您可以添加少量打印并检查正在引用的内存。这会让你更好的理解。

1

这一切都取决于编译器如何实现它?根据标准,您不能在任何本地数据类型中使用任何本地数据类型。