目标 C:块案例中的内存管理

Posted

技术标签:

【中文标题】目标 C:块案例中的内存管理【英文标题】:Objective C: Memory management in Block cases 【发布时间】:2011-06-29 17:18:19 【问题描述】:

我想知道我是否使用如下代码所示的块

__block Loader *loader = [[Loader alloc]initWithResourcePath:self.resourcePath]; 

[loader setCompletionHandler:^(NSArray *anArray)
    self.answerArray=anArray;
    [self reloadData];

];

[loader getObjects];

我的问题是关于内存管理的。分析器告诉我有一个潜在的泄漏(因为我为我的加载器做了一个 alloc/init)。我怎样才能阻止这里的泄漏?我试图在最后释放加载程序,但这会导致我的应用程序停止运行。任何建议在这里表示赞赏

【问题讨论】:

停止运行如何?你得到什么错误?很有可能它会帮助您找到问题的原因。 您将 loader 声明为 __block 有什么原因吗? 【参考方案1】:

几个问题:

没有理由将loader 声明为__block;您没有在块中重新分配,因此,__block 毫无意义。

泄漏是因为你alloc/init加载器,但从未释放它

不要命名方法getSomethingget 前缀是为通过引用返回内容的方法保留的。就叫它objects。如果它应该触发负载,则调用它loadperformLoad

如果是异步的,那么getObjects 是没有意义的。如果是同步的,那么完成块是没有意义的。

如果要同步使用loader,则release在方法的末尾。如果是asynchronous,那么完成块可以释放它。请注意,在这种情况下使用__block 仍然没有意义;虽然在完成块中引用 loader 将创建一个保留周期,但当您明确 Block_release() 块中的 loader 时它将被破坏(因为您必须已经完成了 Block_copy()设置完成处理程序时,如果它首先要异步使用)。

【讨论】:

我在 ASIHTTPRequest (allseeing-i.com/ASIHTTPRequest/How-to-use) 网站上读到,在声明请求时使用 __block 限定符很重要。但是我可以说这个例子是相关的,因为他们实际上在块中使用了 request 吗? 是的,由于我上面描述的原因,只有他们选择在连接完成或出错时不释放块(即一旦不再调用块),从而创建一个循环。我选择使用在对象生命周期中自动中断循环的模式。【参考方案2】:

如果你打算在调用你的块的函数之外使用loader,你很有可能需要将它存储在控制器的 ivar 中(我猜它是一个控制器,但我不知道什么样的类拥有您显示的代码)。完成此操作后,您可以在 dealloc 中发布它。

原因是loader 应该存在于多个方法和运行循环循环中,因此局部变量不会这样做。

否则,一旦你完成它,只需在块的末尾释放它。

如果您觉得这不正确,那么可能需要更多代码。

【讨论】:

【参考方案3】:

我将做一些假设: 1) 完成处理程序(块)由方法 getObjects 使用。 2) getObjects 是异步的(它会立即返回给调用者,尽管它会继续处理)。

根据这些假设,您无法在发送 getObjects 后发送 release,因为 getObjects 仍在使用完成处理程序。

尝试在完成处理程序结束时发送释放或自动释放。那应该释放加载器提供的 reloadData 也不是异步的。

【讨论】:

以上是关于目标 C:块案例中的内存管理的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript 中的性能内存管理

C 内存管理

内存管理相关API列表

matlab和C中的内存管理器问题[重复]

目标 c:使用 NSTimer 对象进行内存管理

ThreadX内核源码分析 - 动态内存管理