2010-07-09 70 views
2

我知道這個問題已經討論過了,但我只是沒有得到一些內存管理。我明白,保留使對象保持活動狀態,並且複製給對象一個單獨的副本。Objective C Memory Management Woes

我不明白的是,當涉及到的ivars &性質,保留的屬性意味着二傳手釋放舊值&保留新:

property = newValue; 
// retain 
if (property != newValue) 
{ 
    [property release]; 
    property = [newValue retain]; 
} 

但我看到的例子,其中他們將靜態字符串分配給retain屬性ivars,例如

self.stringProperty = @"something"; 
(some other code) 
self.stringProperty = @"somethingElse"; 

第二次調用設置字符串應該調用釋放上這是不允許的靜態字符串,爲什麼不程序崩潰?

另外,如果一個對象用retain屬性&聲明,那麼就爲它指定了一些內容,例如,

@property(retain)someArray; 

someArray = [[NSArray alloc] initWithArray:arbArray]; 

這是否意味着現在的someArray具有2的保留計數,但如果它與

someArray = [NSArray arrayWithArray:arbArray]; 

創建保留計數僅爲1,因爲第二個是一個工廠方法?

+0

對不起,我的意思是self.someArray在這兩個樣本。 – 2010-07-12 06:49:32

回答

3

設置字符串的第二個調用應該在不允許的靜態字符串上調用release,爲什麼程序不會崩潰?

您可以將release傳遞給一個常量字符串,它只是不會做任何有意義的事情,所以這些代碼行都是有效的。

是否意味着someArray現在有一個保留計數爲2,但如果它是用...創建的,則保留計數僅爲1,因爲第二個是工廠方法?

嗯,首先,

someArray = [[NSArray alloc] initWithArray:arbArray]; 

不使用由@property創建的方法,它只是直接訪問伊娃。要使用屬性方法,您必須使用self.someArray = ...;

但是,是的,

[[NSArray alloc] initWithArray:arbArray] 

返回一個對象爲1的有效保留計數,並

[NSArray arrayWithArray:arbArray] 

返回一個對象爲0的有效保留計數,因此,如果您將它們傳遞給由@property創建的「保留」制定者,則伊娃將有效保留數分別爲2和1。

+0

謝謝。我不記得所有5 C的良好溝通,但你的答案滿足了我能記得的3個:清晰,簡潔,正確。 – 2010-07-12 06:51:48

0

這是更多的一個問題,但無論如何...

靜態字符串在很多方面都是特殊情況,其中之一就是您可以將retainrelease添加到您的內容中,而不會對其產生任何影響。

順便說一句,NString屬性通常有copy而不是retain語義,如果它重要的話,它將消除這個問題。但事實並非如此。

在第二個的情況下,直接從alloc(或copy或其他所有權授予調用)分配給一個retain屬性是不好的做法,並會泄露,除非你主動過程中添加相應的release之後,或autorelease,例如:

self.someArray = [[[NSArray alloc] initWithArray:arbArray] autorelease]; 

但是在這種特殊情況下真的沒有理由不使用類方法。

+0

關於保留計數的第二部分是我的實際問題,第一部分只是困擾着我,但我將在未來分開提問。感謝您的迴應。 – 2010-07-12 07:31:22

0

設置字符串的第二個調用應該在不允許的靜態字符串上調用release,爲什麼程序不會崩潰?

它不是一個靜態字符串,它是一個常量字符串。但是,這與問題無關,但實際上允許您發送 - 保留到源自NSObject 的任何Objective-C對象,但不包括 NSAutoreleasePool。如果你看看一個常量NSString的retainCount(有點淘氣,但因爲我們正在討論實現,OK),例如,

NSLog(@"retain count = %u", [@"foo" retainCount]); 

你很可能會發現它被設置爲一個非常大的數字(事實上UINT_MAX)。這是運行時忽略要釋放和保留的呼叫的信號。順便說一下,忘記釋放對象不會馬上使程序崩潰。事實上,如果你有很多RAM,你可能會注意到,直到操作系統開始交換。

這是否意味着現在的someArray具有2的保留計數,但如果它與

沒有創建,因爲你沒有使用屬性爲新的數組分配,就直奔ivar:

self.someArray = [[NSArray alloc] initWithArray:arbArray]; 

將是泄漏。

self.someArray = [NSArray arrayWithArray:arbArray]; 

會好的。