2014-01-09 63 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

這一切都取決於編譯器如何實現它?根據標準,您不能在任何本地數據類型中使用任何本地數據類型。