【问题标题】:How can I keep memory usage low with a lot of NSStrings, or how do I release NSStrings?如何使用大量 NSString 保持较低的内存使用率,或者如何释放 NSString?
【发布时间】:2011-07-08 14:18:59
【问题描述】:

我正在开发一个应用程序,该应用程序将(非常)大的 csv 文件导入 Core Data 以进行捕获。这个过程是这样的:

  1. 将文件逐行解析成一个充满 NSStrings 的 NSMutableArray
  2. 在 X 行后,将数组导入 Core Data(这涉及到操作,在某些情况下会创建新的 NSString)
  3. [NSMutableArray removeAllObjects];
  4. 冲洗并重复

乍一看,似乎应该在每个循环结束时释放内存。但是,对于大文件,我发现应用程序在发出几个低内存警告后崩溃。运行泄漏工具告诉我大部分内存都被 CFString 对象用完了,据我所知这与 NSString 对象有关(虽然我不知道如何)

我知道 NSString 会尽可能重用,并且它们的行为与涉及内存的其他对象不太一样,尽管我不了解任何细节。如何回收我的 NSString 对象正在使用的内存?

【问题讨论】:

  • 在将字符串放入数组之前如何存储它?你能发布你的代码吗?
  • 感谢您的建议,它们都是一样的。我已经为我的自动释放对象建立了一个池和/或在适当的情况下使用 init 方法,但该应用程序仍在循环中多次迭代。这对我来说没有意义:因为我在每个循环之间耗尽了我的内存池,所以应该在迭代之间释放内存,对吧?附带说明一下,我已经使用 Leaks 工具确认我的程序中没有内存泄漏,并且我经常对我的代码进行分析以保持状态 - 不过感谢您的建议。
  • 我现在得到了更多细节:至少部分内存正在被释放。当我运行将数据插入核心数据(-insertNewObjectForEntityForName:inManagedObjectContext)的代码时,内存似乎正在积累。我相当定期地执行 -save 操作,所以我认为 Core Data 会处理内存不足的情况,但 Core Data 会不会因为不释放内存而导致问题?
  • 在这项调查中存在一些问题,但最终自动释放池不起作用的原因是因为代码中存在内存泄漏,Leaks 没有始终如一地发现,并且使用 Build & Analyze 完全没有检测到。

标签: iphone objective-c memory nsstring


【解决方案1】:

运行泄漏工具告诉我大部分内存都被 CFString 对象用完了,据我所知这与 NSString 对象有关(虽然我不知道如何)

NSString 实际上是一个类簇。尽管您认为您正在使用 NSStrings,但几乎可以肯定您实际上是在使用它的子类之一。 Cocoa 框架会根据情况选择使用哪个子类。

CFString实际上根本不是真正的NSString,它是Core Foundation使用的纯C字符串对象。但是,您会发现它是“免费桥接”到 NSString 的。这意味着,对于 Cocoa,它看起来像一个 NSString。您看到大量使用 CFString 的原因是因为无论您使用什么 Cocoa API 来获取这些字符串,最终都会在 Core Foundation 中执行其工作。

无论如何,所有这些都与您的问题无关,除了许多 CFString 或多或少意味着与许多 NSString 相同的事实。正如 Girish 已经说过的,您需要减少内存占用的是嵌套的自动释放池。第一步,像这样修改你的算法:

  1. 创建一个新的自动释放池。
  2. 将文件逐行解析成一个充满 NSStrings 的 NSMutableArray
  3. 在 X 行之后,将数组导入 Core Data(这涉及到操作,在某些情况下会创建新的 NSString)
  4. [NSMutableArray removeAllObjects];
  5. 清空自动释放池
  6. 冲洗并重复(从 0 开始)

如果这没有帮助,或者只有一点帮助,请考虑使用自动释放池将解析括起来。

【讨论】:

  • 感谢您提供有关 CFString 的信息!
【解决方案2】:

我假设您没有内存泄漏。

如果你使用了太多的自动释放对象,这可能会发生

你尝试关注

  1. 创建嵌套的自动释放池 --- 有时会发生一些长时间运行的循环,其中自动释放对象会累积。 -- 所以添加自定义自动释放池以在需要时释放自动释放对象。

  2. 不要在解析周期中使用自动释放对象 --- 手动分配对象并在工作完成后释放。

【讨论】:

    【解决方案3】:

    你不能确定内存只被 NSStrings 消耗。我建议你彻底检查一下。尝试进行“构建和分析”,它将帮助您找出漏洞。

    在使用 NSString 对象时,而不是像

    这样的自动释放对象
    [NSString stringWithFormat@""];
    

    创建您自己的对象并在完成后立即释放它。

    NSString * string = [[NSString alloc]initWithFormat:@""];
    //use string object
    [string release];
    

    这样你就可以确定你自己在那里释放了字符串。

    或创建一个自动释放池

    NSAutoReleasePool * pool = [[NSAutoReleasePool alloc]init];
    // do you coding, creation of objects, releasing them, whatever...
    [pool drain]; or [pool release];
    

    也可以看看these memory management tips

    【讨论】:

      猜你喜欢
      • 2011-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-02
      • 1970-01-01
      • 1970-01-01
      • 2010-12-28
      相关资源
      最近更新 更多