2010-04-29 57 views
0

的iPhoneOS 3.2NSData的版本中,不回收內存

我用NSKeyedUnarchiver的unarchiveObjectWithFile:加載包含一個大的NSData和另一個小得多對象的自定義對象。我的自定義對象中的dealloc方法被調用,NSData對象被釋放,其之前的retainCount == 1。物理內存不會減少任何數量,更不用說NSData大小的一小部分了,並且可靠地生成重複內存警告:我有測試,直到我實際收到2級警告。 =(

NSString *archivePath = [[[NSBundle mainBundle] pathForResource:@"lingering"] 
    ofType:@"data"] retain]; 
lingeringDataContainer = [[NSKeyedUnarchiver unarchiveObjectWithFile:archivePath] retain]; 
[archivePath release]; 
[lingeringDataContainer release]; 

現在的dealloc ....

- (void) dealloc { 
    [releasingObject release]; 
    [lingeringData release]; 
    [super dealloc]; 
} 

釋放之前:

(GDB)P(INT)[(NSData的*)lingeringData retainCount]
$ 1 = 1

後:

(GDB)p(INT)[(NSData的*)揮之不去數據保留計數]
目標不響應此消息選擇器。

+0

那麼,你很可能得到,如果lingeringData不再是一個有效的對象。 – 2010-04-30 01:41:48

+0

我應該明白這是我的觀點。它表明我不保留其他地方的NSData對象。 – ctpenrose 2010-04-30 07:22:12

回答

1

首先,您保留並釋放不需要發生的對象。這裏的清理代碼:

NSString *archivePath = [[NSBundle mainBundle] pathForResource:@"lingering"] 
    ofType:@"data"]; // Do not retain again. 
lingeringDataContainer = [NSKeyedUnarchiver unarchiveObjectWithFile:archivePath]; // Do not retain again. 
// Do not release, because archivePath is already autoreleaed: [archivePath release]; 
// Again, this is already autoreleased: [lingeringDataContainer release]; 

或者更簡單地說:

NSString *archivePath = [[NSBundle mainBundle] pathForResource:@"lingering"] 
    ofType:@"data"]; 
lingeringDataContainer = [NSKeyedUnarchiver unarchiveObjectWithFile:archivePath]; 

其次,哪來的代碼的其餘部分?這可能是別的東西被保留或緩存在其他地方。

+0

我需要保留數據容器以備將來使用。再看看gdb輸出,你會發現你對任何緩存都是錯誤的。 – ctpenrose 2010-04-29 22:11:31

+0

我試圖編輯上面的註釋並花了太長時間=(無論如何,我試過你的「清理」代碼,是徹底的,因爲我相當確信它不會給出不同的結果,因爲最後的保留計數是相同的的代碼塊,因爲它是在我的,並且泄漏仍然存在。實際上沒有任何其他代碼 - 它已被刪除以隔離問題。它看起來像NSKeyedUnarchiver中的錯誤,它可能類似於:http://stackoverflow.com/questions/1250050/memory-leak-problem-using-nsdata-in-iphone – ctpenrose 2010-04-29 22:46:55

+0

你的dealloc應該有一個[揮之不去的數據容器版本]然後什麼是延遲數據?是一個單獨的對象還是它一個錯字?你的鏈接中的問題指向一個NSURLConnection。我不知道NSKeyedArchiver有什麼問題。我使用它很多,但是我沒有檢查它的內存使用情況,所以它可能會緩存數據。什麼是字節數據大小? – lucius 2010-04-30 06:40:13

0

您何時檢查內存使用情況?它只是在你發佈的代碼片段之後? archivePathlingeringDataContainer都是自動發佈的。直到(至少)自動釋放池被耗盡(通常在當前事件結束時),它們纔會被釋放。也許還有很多其他的內部資源已經被自動釋放,並且在池被耗盡之前不會消失。

試着這樣做:

NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; // <== 
NSString *archivePath = [[[NSBundle mainBundle] pathForResource:@"lingering"] 
ofType:@"data"] retain]; 
lingeringDataContainer = [[NSKeyedUnarchiver unarchiveObjectWithFile:archivePath] retain]; 
[pool release];            // <== 
[archivePath release]; 
[lingeringDataContainer release]; 
+0

我試圖創建我自己的autorelease池來封裝解除存檔,完成後釋放它,並且內存仍然保留。我重複對對象進行解除存檔的過程時,我通過儀器持續檢查內存使用情況。雖然有些人可能會爭辯說內存並沒有真正佔用,但1級和2級警告說內存保留是真實的。 由於某種原因,NSKeyedUnarchiver很可能不使用iPhoneOS上的本地自動釋放池。 unarchiveObjectWithFile:是一個工廠對象調用... – ctpenrose 2010-05-02 07:54:34

+0

然後我很困惑。 上面的代碼片段不包含任何泄漏,您的原始代碼也不包含任何泄漏,除非在initWithCoder中有泄漏:您能發佈嗎? – JeremyP 2010-05-02 19:51:20