为什么在循环中多次调用subarrayWithRange导致NSMallocException?

时间:2014-05-03 14:02:39

标签: objective-c xcode

我有一个很大的NSArray(wordDictionary),我在for循环中创建了更小的子数组。如果for循环设置为20,000次迭代,一切正常。但是,如果我将for循环迭代增加到200,000次迭代,我会得到一个malloc错误......为什么会这样?

我注意到如果我将子数组赋值从循环内部移动到循环外部,它就解决了问题!(?)请注意,所有子数组在两种情况下都是相同的(这只是为了证明问题)。这是循环内部赋值的代码(导致malloc错误):

    NSArray *subArray;
    //subArray = [wordDictionary subarrayWithRange:(NSRange){50000,20000}];
    for (int i=0;i<200000;i++)
    {
       subArray = [wordDictionary subarrayWithRange:(NSRange){50000,20000}];
       testBool = [subArray containsObject:@"hello"];
    }
    NSLog(@"Done");

如果将子数组赋值移到循环之外(如注释行所示),则上面的代码可以工作

在错误消息中,我得到以下内容:

* mach_vm_map(size = 8388608)失败(错误代码= 3) 错误:无法分配区域 由于未捕获的异常终止应用&#39; NSMallocException&#39; 原因:&#39; * NSAllocateObject():尝试分配类&#39; __ NSArrayI&#39;失败&#39; libc ++ abi.dylib:以NSException类型的未捕获异常终止

有关可能导致此问题以及如何解决问题的任何提示都是受欢迎的!谢谢!

2 个答案:

答案 0 :(得分:3)

我的猜测是你内存不足。每次调用-subarrayWithRange时都会分配一些内存(取决于实现,但可能是20000 *)。

Modern Objective-C使用自动引用计数而不是垃圾回收。这意味着即使您将另一个对象分配给subArray,也不会立即释放内存。

尝试在本地自动释放池中移动它:

for (int i=0;i<200000;i++)
{
    @autoreleasepool {
        // your code
    }
}

答案 1 :(得分:1)

即使您遵循给出的建议并创建自动释放池,这也是非常低效的。每次提取20,000个对象的范围,这意味着将保留20,000个对象并在以后释放,完全没有任何理由。这很容易避免:

for (int i=0;i<200000;i++)
{
   NSRange range = NSMakeRange (50000,20000);
   testBool = [wordDictionary indexOfObject:@"hello" inRange:range] != NSNotFound;
}
NSLog(@"Done");

您还可以考虑NSSet或NSOrderedSet是否不是正确的数据结构。

相关问题