0

我有2個陣列,1在add方法viewDidLoad方法和1(將對象添加到收藏夾)無法釋放陣列對象,但它們都導致泄漏

NSUserDefaults *myDefault = [NSUserDefaults standardUserDefaults]; 
    NSArray *prefs = [myDefault arrayForKey:@"addedPrefs"]; 
    userAdded = [[NSMutableArray alloc] initWithArray:prefs]; 

儀器是示出從泄漏這些首選NSArrays。 (上面只顯示了一個,其他在ViewDidLoad中完全一樣)當我嘗試釋放它們時,應用程序崩潰並且它們在本地定義,所以我無法在dealloc方法中釋放它們。

是否可以將我的userAdded NSMutable數組直接指定給arrayForKey?或者它會導致不匹配?

這個泄漏怎麼可以停止?

回答

0

該文檔不指定initWithArray是否將舊數組(prefs)中的對象添加到新數組(userAdded)時發送額外的保留。它應該,因爲項目被添加到新陣列。也許當舊數組(prefs)被釋放時,userAdded中元素的保留計數太低,對象也被釋放,並且應用程序崩潰。爲了檢查這個問題,我在調用initWithArray之前和之後詢問了第一個數組的內容。

NSUserDefaults *myDefault = [NSUserDefaults standardUserDefaults]; 
NSArray *prefs = [myDefault arrayForKey:@"addedPrefs"]; 
NSUInteger i, count = [prefs count]; 
for (i = 0; i < count; i++) { 
    NSObject * obj = [prefs objectAtIndex:i]; 
    NSLog(@"Object: %@, Retain count: %d.", obj, [obj retainCount]); 
} 
userAdded = [[NSMutableArray alloc] initWithArray:prefs]; 
for (i = 0; i < count; i++) { 
    NSObject * obj = [prefs objectAtIndex:i]; 
    NSLog(@"Object: %@, Retain count: %d.", obj, [obj retainCount]); 
} 

對象報告增加的保留計數,因此可以釋放prefs數組而不影響新數組。但是運行這個代碼仍然會泄漏一個NSArray。

所以這個問題必須存在於prefs數組中。由於NSUserDelfaults方法arrayForKey:產生prefs數組,但在這個方法的名字中沒有找到「alloc」,「new」或「copy」等字,調用方法不擁有prefs數組。最有可能的是,prefs數組被添加到autorelease池中。爲了測試這個想法,我將上述測試代碼與NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];[pool drain]的調用進行了包圍。運行此代碼不會泄漏數組。

所以我認爲prefs數組正在被添加到一個自動釋放池不排水。消除這種泄漏的最簡單方法是在創建prefs數組之前創建自動釋放池,並在使用prefs數組完成時清除該池。

+0

我們不知道'initWithArray:'的內部工作原理,它不如''保留'給出的'NSArray',所以在試圖理解保留計數時存在危險。 (我想:爲什麼不這樣做,因爲'NSArray'是不可變的?它可以跟蹤對'NSArray'的更改,或者僅在寫入時自己創建副本或類似的東西。) – mvds 2010-07-19 13:36:56

+0

「文檔沒有指定initWithArray是否將舊數組(prefs)中的對象添加到新數組時添加額外的保留。數組總是保留其元素 - 或者做一些事情來阻止它們被釋放。 – JeremyP 2010-07-19 15:20:47

+0

現在我很困惑。 我應該使用上述問題中描述的最後一種方法嗎? userAdded = [[NSMutableArray alloc]等copyItems:YES]; – jarryd 2010-07-19 15:25:55

-2

泄漏是你alloc沒有release。每alloc(或copy)應遵循的一個releaseautorelease地方(但不是太快? - 這可能導致您的崩潰)

如果需要扶住userAdded超出了你的函數的範圍,將其作爲保留財產並分配給self.userAdded

因此,使它

self.userAdded = [[[NSMutableArray alloc] initWithArray:prefs] autorelease]; 

,並有

@property (nonatomic,retain) NSMutableArray * userAdded; 

@synthesize userAdded; 

以堵塞漏洞。

+0

謝謝。除了autorelease,我會這麼做,但是Instruments說這是一個泄漏的NSArray。NSArray是NSUserdefaults的prefs數組。如果我在該方法結束時釋放這個首選項,應用程序崩潰了? – jarryd 2010-07-19 13:07:43

+0

這是正確的 - 如果你釋放首選項,你會崩潰。 prefs來自「工廠」方法(即沒有alloc/init的方法),所以它會自動釋放並在該塊超出範圍時釋放。所以,如果它在那裏崩潰 - 好!那就是你想要的! 但是,如果「prefs」發生泄漏,它可能在代碼中的其他位置有保留計數。你能用儀器來顯示對象分配的完整歷史嗎? – makdad 2010-07-19 13:12:09

+1

'NSArray'可能會被'NSMutableArray'保留(見我對其他問題的評論),所以如果你沒有正確地釋放NSMutableArray,它仍然會泄漏。 – mvds 2010-07-19 13:37:50

0

版本的用戶添加到-dealloc