如果我有一個對象,比如在我做副本之前說NSIndexPath,我總是首先釋放它?如果您嘗試釋放已釋放的對象,會發生什麼情況?
是否有可能在0以下的內存計數? 我正在這樣做,以防止內存泄漏..這是一個好方法嗎?
//全球已經在這裏之前有一定的價值,或者沒有價值。我想更新
//這個新值(我不再關心老指針)
[global release]
global = [indexPath copy];
如果我有一個對象,比如在我做副本之前說NSIndexPath,我總是首先釋放它?如果您嘗試釋放已釋放的對象,會發生什麼情況?
是否有可能在0以下的內存計數? 我正在這樣做,以防止內存泄漏..這是一個好方法嗎?
//全球已經在這裏之前有一定的價值,或者沒有價值。我想更新
//這個新值(我不再關心老指針)
[global release]
global = [indexPath copy];
不要。當保留計數達到0時,對象將被釋放並且其指針將失效,因此再次使用它將導致不可預知的結果(即崩潰)。
您應該通讀Apple的Memory Management Guide。
這是基本規則:
更新:
由於喬希指出的那樣,你需要考慮的一個情況是當全球和indexPath是相同的。在這種情況下,你仍然需要指針(執行復制),所以你要麼自動釋放(而不是釋放),要麼使用臨時變量來處理它。
只要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;
}
這可以由通過稍好首先檢查newFloozit
和myFloozit
是否相同,如果是則不做任何事情。
作爲本文的附錄,看看retainCount幾乎總是做錯事。所以不要這樣做,即使是「調試」的目的。 – jer 2011-05-29 15:48:13
我已閱讀此..我現在只是試圖防止內存泄漏,因爲我有一個副本,我發現什麼時候釋放它的硬盤。在使用該變量做另一個副本之前,必須先發布它。 – adit 2011-05-29 15:48:46
這完全是關於所有權。當你需要「取得」對象的所有權時,你增加它的保留計數(無論是通過顯式的'retain'消息,還是通過使用alloc,new,copy或mutableCopy)。當你不再需要它時,你釋放它。只要弄清楚你什麼時候完成了,那就是你何時可以釋放它。 – 2011-05-29 15:51:18