2012-04-27 69 views
0

可能重複:
Can a local variable's memory be accessed outside its scope?爲什麼返回指向本地內存的指針不會摺疊?

我以爲以下調用到f()將獲得一個指針不會被編譯器(根據這是危險的被處理的本地內存到教科書)。但是,它仍然運作良好。不確定這是否安全。

#include <iostream> 

using namespace std; 

int * f() 
{ 
    int v[1000000]; 
    for (int i=0; i<1000000; i++) v[i]=i; 
    cout<<v[7]<<endl; 
    return v; 
} 

int main() 
{ 
    int * v = f(); 
    cout<<v[7]<<endl; 
    return 0; 
} 

回答

4

有趣的問題。您的代碼很可能在某些平臺上運行(或似乎有效)並在其他平臺上失敗。

你的代碼似乎工作的原因是內存中的功能f()儲備棧上發佈但不抹去f()回報。被釋放後,內存可供其他功能使用;但它可能不會被覆蓋,直到另一個函數實際上使用它。

這裏的一些其他人正確地指出你的代碼喚起了未定義的行爲,從技術上講這是真的。但是,有一個原因是你正在得到你所得到的特定的未定義行爲,這就是我的答案。

在包括x86在內的某些平臺上,在f()釋放內存v[]之後,第一個要重用的內存通常是用於存放v[999999]的內存。保存v[0]的內存得到重用可能需要很長時間。因此,來自v[7]的數據虛假地仍然存在。

還有至少一個皺紋。一些使用某些設置的實現可能會立即用隨機數據覆蓋所有釋放的內存,以防範安全風險。 (例如,如果v[]持有密碼,那麼隨機數據將會安全地將其擦除。)

4

指針vmain()是後f()返回懸空指針。解引用一個懸擺指針是不確定的行爲,這意味着任何事情都有可能發生:

  • 它可能崩潰
  • 它可以打印一個不正確的整數值
  • 它可以打印正確的整數值
4

因爲它是未定義行爲,而未定義行爲不一定意味着崩潰。
這是不安全的課程。
一個未定義的行爲意味着所有的安全投注都將關閉,並且可能會發生任何事情,所以如果它沒有崩潰並不意味着它是有效的。這是無效的,你應該不這樣做!

1

未定義的行爲:它可以工作或崩潰,或擦除硬盤驅動器,或爆炸入黑洞,或與妻子一起流失。

雖然有一件事是肯定的:它會導致你失敗​​。

+0

也許將函數'f'重命名爲'demo_undefined_behavior'並得到一個A? – 2012-04-27 15:48:46

1

正如在其他答案中指出的那樣,它是未定義的行爲,所以你不能依賴它的正常工作。它可能在某些平臺或某些編譯器上運行良好,但不是其他編譯器。主要是因爲你的程序很小,很簡單,所以你「擺脫困境」。您越詳細闡述該計劃,您就越有可能遇到問題。

相關問題