2011-05-26 44 views
0

我的應用程序在〜23MB ..iPhone - 3MB文件到一個NSArray的== 22MB

我加載一個3MB文件到一個NSArray如下關停在3G版iPhone ......是海峽和線不自動釋放?任何建議更好的方式來做到這一點?

NSString *str = [NSString stringWithContentsOfFile:path 
       encoding:NSUTF8StringEncoding error:&error]; 
NSArray *lines = [str componentsSeparatedByString: @"\n"]; 
[self parseDictLines:lines]; 


- (void)parseDictLines:(NSArray *)lines { 
    int i = 0; 
    NSMutableArray *arr = [[[NSMutableArray alloc] init] autorelease]; 
    NSMutableArray *word_list = [[NSMutableArray alloc] init]; 
    for (NSString *line in lines) { 
     i++; 
     [arr addObject:line]; 

     if (i == 3) { 
      i = 0; 
      [word_list addObject:[arr copy]]; 
      [arr removeAllObjects]; 
     } 
    } 
    self.mDict = (NSArray*)word_list; 
    [word_list release]; 
} 

編輯 - 應用程序是這樣的代碼之前< 1MB或者如果我跳過這個代碼。它運行後是22mb ...所以它不能成爲臨時變量。它的可用性直到我做了一些增加另一個1mb的值,然後保存它。

EDIT2 - 文件的NSString * str是5.9mb--我假設由於字符串在內存中編碼的方式是UTF8文件的兩倍大。 *行數組也是這個大小。

但是,直到我添加了自動發佈池之後,str才被立即釋放。使用樂器運行需要5分鐘的時間,NSArray *線路才能填滿,在調用[線路釋放]之後,在內存開始消失之前需要大約3分鐘,而在線陣列使用的內存耗盡之前5分鐘之後,到< 1mb。我的mDict數組是14mb。我不知道爲什麼,因爲它沒有那麼多NSArray *行是6mb ...

下面的代碼解決了我的問題,顯然是我在str和行內存釋放之前達到內存限制。現在,str被立即釋放,釋放了6MB,並且當代碼在後臺加載時,用戶無法超越極限。

但 - 爲什麼操作系統傾銷我的應用程序,當我已經自動發佈12mb?它不會清理需要自行發佈的任何內容嗎?

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 
NSString *str = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error]; 
NSArray *lines = [[str componentsSeparatedByString: @"\n"] retain]; 
[pool drain]; 
[self parseDictLines:lines]; 
[lines release]; 
+0

也許不要一次加載整個數組:而是按需加載(分頁或單個條目或什麼)。這需要更多的前期設計,並不一定適用。也許它可能更好地存儲在二叉樹或堆中或利用另一種存儲機制。 – 2011-05-26 02:20:23

+0

如果文件是3MB,我不得不想象一下,基本上NSArray的行數不能超過3mb ......我必須在上面的代碼中犯錯誤。我大概可以將它加入子集,然後根據需要從我們將看到的文件加載剩下的部分。我不想發瘋,因爲我是新來的ObjectiveC – Mark 2011-05-26 03:32:41

+1

在你的應用上運行'instruments',看看你能否識別內存泄漏,它是一個很棒的工具 – Mark 2011-05-26 03:49:37

回答

0

一個辦法是建立一個NSAutoRelease池循環之前,你[arr removeAllObjects]之後瀝乾。排空池與釋放池相同,因此在此之後,您必須再次分配/初始化池。

+0

由於我在22mb峯值,它在代碼運行後停留在那裏我不確定這是否可以解決任何問題,但我明天會玩這個。 str和line會被釋放但不能釋放?排水池釋放autorelease vars?或者釋放內存(垃圾收集) – Mark 2011-05-26 03:37:07

+0

也修復過度保留@thelaws指出。 – 2011-05-26 09:20:53

3

你過度保留arr變量。此時應更換

[word_list addObject:[arr copy]]; 

[word_list addObject:arr]; 
+0

我在循環之前做了一個arr分配,並且在循環中重用了arr,所以我假設我必須[arr copy],否則word_list將以最後一個與我[arr removeAllObjects]相同的空數組的10000個副本結束。 – Mark 2011-05-26 03:24:46

+0

@Mark,你說得對。如果行數不是3的偶數倍,你最終會得到10000個對同一個空陣列的引用(或者1或2行的數組)。 – 2011-05-26 03:29:39

+1

@Mark:可能是這樣,但是你仍然在泄漏數組的副本。用'[word_list addObject:[[arr copy] autorelease]]替換'[word_list addObject:[arr copy]];'' – 2011-05-26 04:48:57

0

通過Instrument's Allocations儀器運行它,您應該能夠看到內存的位置。