iOS 过早释放对象 - 可能与 Autorelease 和 Copy 混淆

Posted

技术标签:

【中文标题】iOS 过早释放对象 - 可能与 Autorelease 和 Copy 混淆【英文标题】:iOS Releasing object too early - possible confusion with Autorelease and Copy 【发布时间】:2011-09-01 08:00:25 【问题描述】:

我编写了一个包含自定义搜索类的应用程序。这会构建一个结果数组。

然后我将该数组分配给我的 FirstViewController 类,并重新加载一个表格视图,其中分配了结果数组

self.aResults = [thisSearch.aResults copy]
...
[[self searchResults] reloadData];

在此之后不久,我将发布 thisSearch

[thisSearch release];

这一切都很好,并显示了结果表,但是如果我向下滚动表格并查看下面的行它们都是空白的,那么当我向上滚动应用程序时,它会在重新加载回收的表格单元格时崩溃。

这在我之前没有发生过,但我意识到我正在泄漏内存,所以我发疯了 autorelease,并在我的 中添加了很多 autorelease搜索 类。但不是我的 FirstViewController 类。

所以如果我使用Copy,它实际上并没有复制对象,它只是增加了引用计数器吗?因此,当我销毁 Search 时,我是否会销毁其中的结果数组,从而销毁 FirstViewController 试图访问表视图的内容?

对不起,如果这没有多大意义,我今天不太适应。

【问题讨论】:

您应该创建一个像@property (nonatomic, copy) NSArray *aResults; 这样的Results 复制属性,而不是self.aResults = [thisSearch.aResults copy]。然后,当您设置此属性时,它将自动获取您设置的对象的副本。处理完 aResults 中的任何内容后,执行self.aResults = nil,它将被释放。我没有将此作为答案提交,因为它只是一个提示,但这不是您的应用程序崩溃的原因。而且没有更多代码,我不知道为什么会这样。 【参考方案1】:

当您 copy 对象时(并且要这样做,该对象必须符合 NSCopying 协议,但 NSArray 就是这种情况),就像您第一次使用 initializing 它一样预定义值。

因此,您对 release 的对象负责,这些对象已成为 copied

你必须这样做:

self.aResults = [thisSearch.aResults copy]
...

[thisSearch release]; // When you release thisSearch this will not affect aResults
...

// then you can either do:
[self.aResults autorelease]; // but then do not release it later on
// or
[self.aResults release]; // when you're done with it

但是我怀疑这会解决你的记忆问题。通过过度自动释放(并且仍然释放东西),您可能已经完全破坏了您的应用程序内存管理。

要尝试修复它,请尝试分析您的项目,看看会发生什么。

我还附上了Apple Memory Management link,人们应该每月阅读它,直到它成为第二天性。

【讨论】:

啊啊我应该运行分析!我运行了它,它指向一个我正在自动释放的 NSDicitonary,并告诉我引用计数器已经为 0,因为我将该字典分配给一个也是自动释放的数组 - 所以我想它试图释放那个字典当它所在的数组已经消失时

以上是关于iOS 过早释放对象 - 可能与 Autorelease 和 Copy 混淆的主要内容,如果未能解决你的问题,请参考以下文章

ios:多次使用相同的sqlite参数会导致过早的内存释放

iOS中常见 Crash 及解决方案

何时释放/保留传递给辅助线程的对象?

MFC误报内存泄露的修复

MFC误报内存泄露的修复

人们是不是训练过早停止的对象检测方法?他们的设置是啥?