2012-01-05 32 views
13

說我有以下兩個功能:用C局部變量的寄信人地址

int * foo() 
{ 
    int b=8; 
    int * temp=&b; 
    return temp; 
} 

int * foo() 
{ 
    int b=8; 
    return &b; 
} 

我沒有得到任何預警第一個(例如函數返回本地變量的地址)但是我知道ow這是非法的,因爲b從堆棧中消失,我們剩下一個指向未定義內存的指針。

所以,當我需要小心返回臨時值的地址?

回答

17

你沒有得到的第一個片段一個警告的原因是因爲你不是(從編譯器的角度來看)返回一個地址給一個局部變量。

您正在返回的int * temp值。儘管這個變量可能是(並且在這個例子中是)包含一個作爲局部變量地址的值,但編譯器不會上去執行代碼棧來查看是否是這種情況。

注意的片斷兩者都同樣糟糕,即使你的編譯器不會警告你了前者。不要使用這種方法。


返回局部變量的地址時,你一定要加倍小心;作爲一項規則,你可以說你從來沒有應該。

static變量是一個完全不同的情況下,雖然,這是在this thread正在討論之中。

+1

謝謝!以及當我在主打印返回值的時候,它會得到正確的結果,這實際上意味着它打印垃圾? – mary 2012-01-05 13:42:24

+3

這意味着你正在調用我們通常所說的* [未定義的行爲](http://en.wikipedia.org/wiki/Undefined_behavior)*,即。在標準中未指定的行爲。 – 2012-01-05 13:46:23

-2

這些都是壞的,一個好的編譯器應該能夠探測和警告兩種情況。您可以通過將警告級別設置爲最大值(您始終應該這樣做)來獲得更好的結果,並打開優化。

+0

具體情況,也許。但是也有很多類似的情況涉及將地址與其他變量(或通過其他函數)進行混洗,而編譯器根本無法檢測到這些變量。此外,優化很少會增加檢測此類問題的機率 - 它只會增加出現可觀察效果的問題的可能性。 – Rob 2015-02-03 00:07:53

+0

當然,有些編譯器無法檢測的情況,但這些特定情況應該很容易檢測到。優化是有效的,因爲它將第一個例子減少到第二個例子 – harald 2015-02-04 08:45:40

+1

對不起,不對。當談到編譯器的實施質量時,幾乎沒有「應該」 - 這些都是基於他們自己的成本/收益分析的供應商決策,這可能不符合開發人員的先入之見。構造示例(例如可能會改變指針的函數調用)也很容易,這意味着您聲稱的優化可能不可行 - 這也使得供應商決定是否優化這些事情,而不是給定的。 – Rob 2015-02-04 09:05:28

0

這兩個示例同樣不正確。我的猜測是你的編譯器沒有看到危險,因此當你將地址存儲在臨時變量中時不會發出警告。

1

我要說的是,你可以返回局部變量或者說指針,例如,如果它是通過動態分配的malloc,在這種情況下,用於存儲變量的存儲要放在棧但堆和不會被清零或在退出函數後重新使用,因爲它在自動局部變量(沒有malloc創建)的情況下發生,我說得對嗎?