2010-05-28 29 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