2011-05-29 93 views
1

如果我有一個對象,比如在我做副本之前說NSIndexPath,我總是首先釋放它?如果您嘗試釋放已釋放的對象,會發生什麼情況?

是否有可能在0以下的內存計數? 我正在這樣做,以防止內存泄漏..這是一個好方法嗎?

//全球已經在這裏之前有一定的價值,或者沒有價值。我想更新
//這個新值(我不再關心老指針)

[global release] 
global = [indexPath copy]; 

回答

8

不要。當保留計數達到0時,對象將被釋放並且其指針將失效,因此再次使用它將導致不可預知的結果(即崩潰)。

您應該通讀Apple的Memory Management Guide

這是基本規則:

  • 你只釋放或自動釋放對象你自己。如果您使用名稱以「alloc」,「new」,「copy」或「mutableCopy」(例如alloc,newObject或mutableCopy)開頭的方法創建它,或者如果您發送它保留消息。
  • 您使用release或autorelease放棄對象的所有權。 autorelease只意味着「將來發送一條發佈消息」(具體來說:當使用的autorelease池收到一條消息時)。

更新:

由於喬希指出的那樣,你需要考慮的一個情況是當全球和indexPath是相同的。在這種情況下,你仍然需要指針(執行復制),所以你要麼自動釋放(而不是釋放),要麼使用臨時變量來處理它。

+4

作爲本文的附錄,看看retainCount幾乎總是做錯事。所以不要這樣做,即使是「調試」的目的。 – jer 2011-05-29 15:48:13

+0

我已閱讀此..我現在只是試圖防止內存泄漏,因爲我有一個副本,我發現什麼時候釋放它的硬盤。在使用該變量做另一個副本之前,必須先發布它。 – adit 2011-05-29 15:48:46

+0

這完全是關於所有權。當你需要「取得」對象的所有權時,你增加它的保留計數(無論是通過顯式的'retain'消息,還是通過使用alloc,new,copy或mutableCopy)。當你不再需要它時,你釋放它。只要弄清楚你什麼時候完成了,那就是你何時可以釋放它。 – 2011-05-29 15:51:18

0

只要global具有您不再需要的舊值或nil,您所做的事情本質上是正確的。如果它是一個類的ivars中的一個,那麼當類的一個實例被創建時它將是nil。一個問題是,如果新的indexPath碰巧與global中已有的對象相同,那麼您將發生過度釋放並且會崩潰。

// global points to object at 0x8BADFOOD 
// indexPath also happens to be 0x8BADFOOD; for some reason, it 
// hasn't changed since last time. This _can_ happen. 
[global release]; // object at 0x8BADFOOD is deallocated 
global = [indexPath copy]; // indexPath no longer valid! 
           // Crash! Bang! Boom! 

避免這種情況的方法是使用臨時變量。

當你聲明屬性爲copy和合成該屬性,創建的setter方法看起來基本上是這樣的,你可以做同樣的事情:

- (void)setMyFloozit:(Floozit *)newFloozit { 
    // Copy first in case newFloozit and myFloozit are for 
    // some reason the same object 
    // Take ownership of a copy of newFloozit 
    Floozit * tmp = [newFloozit copy]; 
    // We no longer need old value of myFloozit, so we release it. 
    [myFloozit release]; 
    // tmp contains a value that we own, we just need to assign 
    // it to the correct name. 
    myFloozit = tmp; 
} 

這可以由通過稍好首先檢查newFloozitmyFloozit是否相同,如果是則不做任何事情。

相關問題