2010-08-10 71 views
3

如果* get_ii()返回堆內存,而不是堆棧內存,這個問題是否會被消除?指針電阻

01 int *get_ii() 
02 { 
03 int ii;  // Local stack variable 
04 ii = 2; 
05 return ⅈ 
06 } 
07 main() 
08 { 
09 int *ii; 
10 ii = get_ii(); // After this call the stack is given up by the routine 
11     // get_ii() and its values are no longer safe. 
12  
13 ... Do stuff 
14 .. ii may be corrupt by this point. 
15 } 

來源 - http://www.yolinux.com/TUTORIALS/C++MemoryCorruptionAndMemoryLeaks.html

感謝

+0

與返回引用相同的問題,自動對象的生命週期以範圍結束。在大多數情況下,只需返回一個值。(Do * not * pre-optimize and say「哦,但是我會複製一個大對象,所以我不應該那樣做!我會通過引用作爲參數或返回一個指向動態分配值的指針「但是不要。) – GManNickG 2010-08-10 17:51:17

回答

7

是的。從堆分配將在這裏工作。確保你再次釋放它,否則你會泄漏內存。

智能指針通常會幫助您處理這種「不要忘記」的邏輯。

+1

智能指針+1。不使用RAII這種事情可能是一個壞主意。 – Brian 2010-08-10 17:48:22

+1

返回一個值幾乎肯定會更好。即使對象足夠大,複製速度會比分配速度慢,但大多數編譯器都會無視這一副本。 – 2010-08-10 18:48:40

+0

所以問題是,一旦它從get_ii函數中釋放,返回的ii地址就意味着什麼? – 2010-08-10 19:14:56

2

,因爲當你在主訪問II將發生在你的代碼的問題,get_ii()返回之後,你的變量通過II訪問時已經被破壞。

如果返回分配了從get_ii堆內存,那麼內存可以被訪問,直到它被顯式銷燬

3

右鍵 - 從堆(使用malloc分配的,例如)內存將持續外get_ii()的範圍。只要確保釋放它。你也可以分配ii作爲static int ii,在這種情況下,它的指針也會存在於get_ii()之外。

+2

雖然,一個警告是將其聲明爲」靜態「,然後將其設置爲所有調用該函數的副本。這是一個設計決定,應該通過預先考慮和理解來做出,並且絕對不是在多線程程序中應該做的。 – Omnifarious 2010-08-10 17:55:48

+0

它甚至不需要線程成爲一個問題。如果程序中的一個點獲得指針並保持在其上,則另一個點可以做同樣的事情,並且在一個地方對值的更改會影響另一個點。 – KeithB 2010-08-10 19:37:13

3

您基本上返回不再存在的變量的地址(ii在函數get_ii()開始執行時創建,並且僅在函數退出之前存在)。對main()int *ii指向的內存的任何訪問都會導致未定義的行爲。

另一方面,堆內存是在您明確請求它時分配的,並且在您明確請求它之前不會釋放它。所以如果你在一個函數內部分配一個內存塊,把指針返回給那個內存塊是非常好的。只需確保在不再需要時釋放內存塊的人員負責記錄誰是誰!

0

如果你正在編寫C風格的代碼,那麼要做的事情就是傳入一個指向對象的指針並通過該指針修改對象。這樣get_ii函數不用擔心對象來自哪裏。調用函數會照顧它。

如果你正在編寫C++風格,那麼你應該返回值或返回一個智能指針或採取引用並通過該引用修改對象。或者你可以使用C風格並傳遞一個指針。一些C++作者更喜歡指針傳遞,因爲它明確指出對象正在被修改,而引用傳遞不明確。

現在,如果對象在這個例子中很小,那麼您應該總是按值傳遞並返回它。它比使用指針更快,更便宜,並且使編碼更簡單。

+0

即使返回的對象很大,返回值優化可能允許編譯器在它返回的位置構造它,以消除任何複製。 – jcoder 2010-08-10 18:05:14

+0

如果你正在返回一個結構體,通常的ABI實際上將一個指向一個結構體的指針作爲第一個參數來填充,使它等價於pass-a-pointer版本。由於潛在的異常(也可能是線程),會有一些差異,但是如果您分配給本地,它應該做正確的事情(並且可能會優化得更好)。 – 2010-08-10 18:58:37

2

甚至更​​惡毒:

std::string& makeString() //returns a reference 
{ std::string str = "Dustin"; return str; } 

main(){ 
std::string s = makeString(); 
//s is a dangling reference! makeString returns a reference to str, 
//but str is on the stack and goes out of scope, so we're keeping a reference to nothing 
} 

STR(內部makeString)是在堆棧上和makeString返回時被破壞。 通過返回by-value而不是by-reference來解決此錯誤,這會在str超出範圍之前對str進行復制。

+0

我認爲堆棧變量被破壞?其次,這個錯誤如何解決? – 2010-08-10 19:27:48

+0

更新了我的答案 – 2010-08-10 19:53:34