2012-11-01 51 views
1

可以說我有下面的代碼:困惑內存管理與保留/自動釋放

@property (nonatomic, retain) *SomeObject foo; 
@property (nonatomic, retain) *SomeObject bar; 

@synthesize foo, bar; 

self.foo = [[SomeObject alloc] init]; 
self.bar = [[[SomeObject alloc] init] autorelease]; 

if (self.foo) { 
    [self.foo release]; 
    self.foo = nil; 
} 

if (self.bar) { 
    [self.bar release]; 
    self.bar = nil; 
} 

我得到self.bar內存泄漏。我不完全確定爲什麼,但我認爲這是因爲在調用[self.bar發佈]後,對象self.bar指向獲取autoreleased。當我清零self.bar時,我們嘗試調用前一個對象(獲得autoreleased)的釋放,這會產生錯誤。它是否正確?另外,還有其他內存泄漏,可能與富? 什麼是正確的修復?

我應該刪除發佈聲明,只是零這兩個屬性?

+0

*咳嗽* ... ARC ... *咳嗽* –

+2

@ RichardJ.RossIII如果我是你,我會很高興有人真的不理解MRC是如何工作的... – 2012-11-01 23:18:19

+0

@ h2co3也許。但至少閱讀一些文章或拿起一本書,而不是不斷地發佈具有不同屬性名稱的相同問題。 –

回答

2

你應該只直接使用存取:

self.foo = [[[SomeObject alloc] init] autorelease]; 
self.bar = [[[SomeObject alloc] init] autorelease]; 

if (self.foo) { 
    self.foo = nil; 
} 

if (self.bar) { 
    self.bar = nil; 
} 

因爲合成的屬性訪問器生成執行引用計數操作的代碼。

永遠不要使用表格[someObject.someProperty release]

唯一不應該使用存取器的地方是處於部分構造狀態(即初始化和dealloc)。在這種情況下,使用直接訪問:[ivar release], ivar = nil;

+0

謝謝,你能解釋爲什麼永遠不應該使用form [someObject.someProperty release],但是如果我們使用ivar可以嗎?除了我調用一個返回foo的方法外,不是self.foo與foo相同嗎?如果我這樣做會是什麼問題? – Popcorn

+0

這實際上是多餘的:'if(self.foo){self}。foo = nil; }'。只需'self.foo = nil;'更容易閱讀和更好的風格。 –

+0

@Popcorn因爲返回的對象可能不是活動ivar的同一實例(例如併發和覆蓋是典型的場景)。儘管您可以保證在某些受限制的環境中它是相同的指針,但它是大量維護並且完全沒有必要。 IOW會削弱班級界面的正確性。 – justin

1

有錯誤的代碼中的3個地方:

@property (nonatomic, retain) *SomeObject foo; 
@property (nonatomic, retain) *SomeObject bar; 

self.foo = [[SomeObject alloc] init]; // WRONG 1 
self.bar = [[[SomeObject alloc] init] autorelease]; 

if (self.foo) { 
    [self.foo release]; // WRONG 2 
    self.foo = nil; 
} 

if (self.bar) { 
    [self.bar release]; // WRONG 3 
    self.bar = nil; 
} 

在任何方法中,你必須平衡保留和釋放,除非你是在對象上直接設置實例變量。你不直接設置任何實例變量。你正在使用屬性(這是方法調用)。

1是錯誤的,因爲alloc返回一個保留實例(你(這個方法)「擁有」它,因此你必須在它離開你的範圍之前釋放它)。你將它傳遞給一個方法(屬性設置器),然後你不再有它的引用。因此它被泄漏。

2和3是錯誤的,因爲你正在釋放你不擁有的東西。屬性訪問是一種方法調用,普通方法調用不返回保留實例。

錯誤1和錯誤2恰好平衡 - 有很多錯誤,他們碰巧以錯誤的方式取得正確的結果。錯誤3應該會導致程序崩潰,因爲你是過度釋放。