【问题标题】:Memory not being freed correctly?内存没有被正确释放?
【发布时间】:2011-05-16 11:52:03
【问题描述】:

我的应用程序以特定顺序从 URL 下载图像,然后用户查看它们。我让应用程序预加载下一张图片并将旧图片保存在缓存中。

这个缓存基本上是一个 NSMutableDictionary,其中的键与图像 ID 相关联。缓存中的每个对象也是一个带有 url、图像 URL、标题和 NSData 对象的 NSDictionary。当我下载图像时,我将一个新的字典对象添加到带有这些元素的缓存中。我像这样存储 NSData 对象: NSData *imgData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:imageurl]];然后我将此对象添加到子字典对象中。

这显然在存储和缓存大量照片后会占用大量RAM,因此我通过清除整个缓存来响应内存警告。问题是,无论我尝试了什么,都没有释放 RAM。对象消失(就像它们应该消失的那样),但不要归还 RAM。我尝试过以下操作:

  • 循环缓存字典,释放子字典中的数据对象,然后当所有项都循环通过时,移除所有缓存字典子对象。
  • 循环缓存字典,释放子字典,完成后删除所有对象
  • 即使删除所有对象,然后释放整个缓存对象(然后重新创建它,因为它仍然需要使用)
  • 以及其他随机释放、移除等组合。

问题是,我没有尝试释放内存。释放 NSData 对象的内存时我做错了什么吗?

【问题讨论】:

  • 下载数据时使用什么缓存策略?您是否确认(即通过 Leaks 或 Allocations)内存肯定被泄漏或放弃了?
  • 我实际上并没有使用任何内置于 iOS SDK 中的缓存——我正在使用一个充满 NSData 对象(包含图像)的 NSDictionary 来管理我自己的缓存。每当我从字典中删除所有对象时,都不会释放内存。我不确定这个内存到底分配在哪里,但它并没有像我想要的那样被释放。

标签: iphone objective-c memory nsdictionary nsdata


【解决方案1】:

Objective-C 中内存管理的工作方式是您通过分配/初始化、-retaining 或-copying 获得对象的所有权,并在不再需要时通过-release 或-autorelease 将其关闭。

你想做的是:

1) 创建数据对象

NSData *imgData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:imageurl]]; 

您现在拥有 imgData 指向的对象。

2) 将该对象添加到您的子字典中

[childDictionary setObject:imgData forKey:@"imgData"];

3) 关闭数据对象。你不再需要它了。 childDictionary 需要它,但这不是你的问题。 childDictionary 与其他所有对象一样,负责管理自己的内存和所有权。

[imgData release];

另一种方法是创建数据对象的自动发布版本,并将其添加到字典中。

接下来,您需要确保正确管理childDictionary 的内存以及cache 的内存。例如:

1) 创建一个自动发布的 childDictionary

NSMutableDictionary *childDictionary = [NSMutableDictionary dictionary];

2) 向 childDictionary 添加内容(就像我们之前所做的那样)

3) 将 childDictionary 添加到缓存中

[cache setObject:childDictionary forKey:yourKey];

4) 由于 childDictionary 是自动发布的,因此您不需要(也不应该)发布它,因为您不需要它。稍后将由主自动释放池自动释放。如果您使用以下方法创建了 childDictionary:

NSMutableDictionary *childDictionary = [[NSMutableDictionary alloc] init];

它返回一个 retainCount 为 1 的对象,那么您现在需要解除所有权:

[childDictionary release];

就缓存而言,您可能希望将其保留很长时间:它很可能是管理缓存的任何对象的实例变量,当您遇到内存警告时,它会使用[cache removeAllObjects] 重置。

如果您在 Mac 上使用垃圾收集进行开发,那么所有这些都是无用的。但是既然你在打电话,你就需要知道这些关于内存管理的简单规则。我的解释确实忽略了很多你应该熟悉的概念,所以我强烈建议你阅读the Apple documentation about this

【讨论】:

    【解决方案2】:

    演示此泄漏的简化代码示例会有所帮助。仅根据您的描述,您用于将 imgData 添加到字典的调用是否可能会保留它?如果您没有立即在自己的代码中释放 imgData,则保留计数为 2。当您的本地 imgData 指针超出范围时,您将泄漏内存。不过,这只是在没有代码示例的情况下摸索。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-27
      • 1970-01-01
      • 1970-01-01
      • 2017-12-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多