2010-05-28 61 views
3

我在我的iphone應用程序中構建一個字典數組(稱爲鍵),以保存tableview的段名稱和行數。內存有效的集合類

的代碼如下所示:

[self.results removeAllObjects]; 
[self.keys removeAllObjects]; 

NSUInteger i,j = 0; 
NSString *key = [NSString string]; 
NSString *prevKey = [NSString string]; 

if ([self.allResults count] > 0) 
{ 
    prevKey = [NSString stringWithString:[[[self.allResults objectAtIndex:0] valueForKey:@"name"] substringToIndex:1]]; 

    for (NSDictionary *theDict in self.allResults) 
    { 
     key = [NSString stringWithString:[[theDict valueForKey:@"name"] substringToIndex:1]]; 

     if (![key isEqualToString:prevKey]) 
     { 
      NSDictionary *newDictionary = [NSDictionary dictionaryWithObjectsAndKeys: 
              [NSNumber numberWithInt:i],@"count", 
              prevKey,@"section", 
              [NSNumber numberWithInt:j], 
              @"total",nil]; 

      [self.keys addObject:newDictionary]; 
      prevKey = [NSString stringWithString:key]; 
      i = 1; 
     } 
     else 
     { 
      i++; 
     } 
     j++; 

    } 

    NSDictionary *newDictionary = [NSDictionary dictionaryWithObjectsAndKeys: 
            [NSNumber numberWithInt:i],@"count", 
            prevKey,@"section", 
            [NSNumber numberWithInt:j], 
            @"total",nil]; 

    [self.keys addObject:newDictionary]; 

} 

[self.tableview reloadData]; 

代碼通過正常工作第一次,但我有時不得不重建整個表,所以我重做這個代碼,獸人在模擬器上很好,但我的設備上程序炸彈當我執行reloadData行:

malloc: *** mmap(size=3772944384) failed (error code=12) 
*** error: can't allocate region 
*** set a breakpoint in malloc_error_break to debug 
malloc: *** mmap(size=3772944384) failed (error code=12) 
*** error: can't allocate region 
*** set a breakpoint in malloc_error_break to debug 
Program received signal: 「EXC_BAD_ACCESS」. 

如果我刪除reloadData行代碼在設備上工作。

我想知道這是否與我建立的鍵陣列(即使用自動釋放字符串和字典)的方式。

回答

15

錯誤消息是給你一個非常明確的原因分配失敗:

malloc: *** mmap(size=3772944384) failed (error code=12) 
*** error: can't allocate region 
*** set a breakpoint in malloc_error_break to debug 
malloc: *** mmap(size=3772944384) failed (error code=12) 
*** error: can't allocate region 

具體來說,大小爲3772944384;差不多4GB。即你要求malloc()分配一些導致malloc的東西,認爲它需要內存映射(mmap)將近4GB的地址空間!如果你的輸入字符串真的很沉重,那麼你的代碼會像davydotcom說的那樣膨脹autorelease池,但是他們必須真的很大才會導致這種情況發生。如果它那麼巨大,那麼你的表格中有幾十或幾十萬行呢?如果是這樣,那麼不要這樣做 - 用戶很難處理。

正如錯誤所述,在malloc_error上設置一個斷點併發布回溯。

需要注意的是這樣的:

NSString *key = [NSString string]; 
NSString *prevKey = [NSString string]; 

是無稽之談。

好的 - 再次查看您的代碼表明,對Objective-C guideCocoa memory management指南的審查將會很有用。

在前四行代碼中,您都泄漏了前一個並且保留了新的self.keysself. self.results(假設它們都應該是retain屬性)。

請嘗試使用Build &分析您的代碼。

+0

+1可用性問題 – 2010-05-28 17:24:50

+0

字符串非常小,表中大約有500行。我會嘗試斷點...... – Joe 2010-05-28 17:54:51

+0

好的 - 這可能是一段時間內建立起來的泄漏情況。或者它可能是一個過度釋放的對象,然後導致某人要求一個荒謬的malloc()。殭屍和分配工具也可能會幫助你很多。 – bbum 2010-05-28 17:59:17

0

如果可能,我會強烈建議不要使用自動釋放的字符串和對象,因爲它們也會降低性能。代碼集中的所有內容除了最上面的奇數語句之外都是正確的。

第2行中刪除所有來自數組對象,那麼你指定指向新self.keys和self.results

分配self.keys和self.results只有一次,重新加載數據時,只需撥打removeAllObjects 。

+0

合理的建議,但不是這裏的問題。 – bbum 2010-05-28 17:01:20

+1

建議您在不進行測試的情況下,以可讀性爲代價優化性能。這是不好的建議。自動釋放對象的性能通常會降低一個百分點,並且會(除其他之外)修復此代碼中的幾處內存泄漏,您已經錯過了並聲明「一切看起來正確」。 自動釋放是有原因的:沒有簡單的模式就可以使所有這些東西都正確* hard *。 – 2010-05-28 18:21:22

+0

你是對的關於頂部的2行(重新分配鍵和結果)。他們從我參加的一項測試中被留下。我已經從代碼中刪除了它們。 – Joe 2010-05-29 08:22:23

0

稱爲鍵的字典數組... [self.keys addObject:newDictionary] .. needs .. lie .. down。

+1

感謝downvote,我現在看到這是一個出色的命名方案,問題在別處。 – hooleyhoop 2010-07-28 22:02:58

+0

問題在別處,但給了你有趣的評論upvote。命名方案是可怕的,並且最有可能使得調試該問題比所需要的更困難:) – JOM 2011-09-26 05:08:01