【问题标题】:iPhone - 3mb file into a NSArray == 22mbiPhone - 3mb 文件到 NSArray == 22mb
【发布时间】:2011-05-26 02:16:04
【问题描述】:

我的应用在 3G iPhone 上以约 23mb 的速度关闭。

我正在将一个 3mb 文件加载到 NSArray 中,如下所示... str 和 lines 不会自动释放吗?关于更好的方法来做到这一点的任何建议?

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 文件的两倍。 *lines 数组也是这个大小。

然而,直到我添加了自动释放池,str 才被立即释放。使用仪器运行时,NSArray *lines 需要 5 分钟才能填满,在调用 [lines release] 之​​后,在内存开始消失之前大约需要 3 分钟,然后在 *lines 数组使用的内存关闭之前需要 5 分钟

下面的代码解决了我的问题,这显然是我在 str 和 lines 内存被释放之前达到了内存限制。现在 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];

【问题讨论】:

  • 也许不会一次加载整个数组:而是按需加载(分页或单个条目或诸如此类)。这将需要更多的前期设计,并且可能并不总是适用。也许它可能会更好地存储在二叉树或堆中,或者使用其他存储机制。
  • 如果文件是 3mb,我不得不想象什么基本上是一个 NSArray 的行不能超过 3mb ......我一定是在上面的代码中犯了一个错误。我可能可以将其子集化,然后从我们将看到的文件中按需加载其余部分。我不想发疯,因为我是 ObjectiveC 的新手
  • 在您的应用程序上运行instruments,看看您是否可以识别内存泄漏,这是一个很棒的工具
  • 你的文件有多少行?任何 unicode 字符?
  • 当你说应用在这段代码之前

标签: iphone memory-management


【解决方案1】:

您过度保留了 arr 变量。你应该替换

[word_list addObject:[arr copy]];

[word_list addObject:arr];

【讨论】:

  • 我在循环之前做 arr 的分配并在循环中重用 arr 所以我假设我必须 [arr copy] 否则 word_list 最终会得到与我相同的空数组的 10000 个副本[arr removeAllObjects] 最后。
  • @Mark,你说得对。你最终会得到 10,000 个对同一个空数组的引用(或者如果行数不是 3 的偶数倍,则为 1 或 2 行的数组)
  • @Mark:可能是这样,但您仍在泄漏数组的副本。将[word_list addObject:[arr copy]]; 替换为[word_list addObject:[[arr copy] autorelease]];
  • 我刚刚再次阅读了内存管理文档,谢谢。 developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/…
【解决方案2】:

一种方法是在循环之前设置一个 NSAutoRelease 池,在 [arr removeAllObjects] 之后立即排出。耗尽池与释放池相同,因此之后您必须再次分配/初始化池。

【讨论】:

  • 因为我的峰值是 22mb,并且在这段代码运行后它一直存在,我不确定这能解决什么问题,但我明天会解决这个问题。 str 和 lines 是否可以被释放但没有被释放?排空池释放自动释放变量?或者也释放内存(垃圾收集??)
【解决方案3】:

通过 Instrument 的 Allocations 工具运行它,您应该能够看到内存的去向。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-17
    相关资源
    最近更新 更多