NSThread 内存泄漏

Posted

技术标签:

【中文标题】NSThread 内存泄漏【英文标题】:NSThread Memory Leak 【发布时间】:2013-02-15 00:15:03 【问题描述】:

我正在使用如下的 NSThread

NSThread * thread = [[NSThread alloc] initWithTarget:object selector:@selector(bg) object:nil];
[thread start];

稍后我想停止线程并释放对象,如下所示:

[thread cancel];
[object release];

这似乎工作正常。但是,当我查看泄漏工具时,我看到一些神秘的泄漏不是来自我的代码的任何地方(一个空的 NSArray)。当我查看 malloc 历史记录时,我看到 NSArray 是在“willChangeValueForKey”方法中分配的,该方法最终从我的 [object dealloc] 调用。它恰好将委托设置为零。该委托正在被观察(因此 willChangeValueForKey?)。 [object dealloc] 从 [NSThread exit] 调用。

我的猜测是,这是因为 [线程取消] 不会立即停止线程(毕竟它在不同的线程中)。然后我们在主线程上释放对象。 这使得它的 retainCount 为 1。然后 NSThread 将在它真正减速时释放对象。看来这会导致泄漏。我尝试了这个快速更改来验证我的假设:

[thread cancel];

[NSThread sleepForTimeInterval:1];
// This makes it wait until the thread releases [object]

[object release];

问题:为什么让 NSThread 释放我的对象是不安全的?是否与dealloc中的观察者代码不安全有关?

【问题讨论】:

您的willChange/didChange 是否发生在addObserver:removeObserver: 被调用的同一线程上? 你的线程有自己的自动释放池吗? 自动释放池:是的。至于 iluvcapra 的问题:我不确定。这段特殊的代码非常复杂,所以我不能 100% 确定。将它们放在不同的线程上会导致泄漏吗? 您可以想象一场比赛,其中一个线程正在执行观察例程,而另一个线程正在将其作为观察者移除。 【参考方案1】:

您的主线程应该能够立即[object release],您不必等到取消线程,甚至直到您启动它。 initWithTarget: 隐式保留 objectcancel 隐式释放它。

您不必在主线程上保留object 以使其保持活动状态,以便为分离线程的缘故。

【讨论】:

还有其他原因我需要保留object。但我也不确定这是否会有所帮助。当发布从我启动的线程发生时,它似乎搞砸了。 我进行了一些重构,以使object 不会持有太多东西,因此可以安全地随时释放它。我发现问题实际上在于object 正在抓住另一个正在观察自身的对象。根据一些研究,观察自我似乎不是一个好的模式。所以这可能是这里真正的解决方法,也是我最终要做的。尽管分解出 NSThread 特定的东西是合理的。感谢您的帮助。 我之前观察过self,它可以工作,但是跨线程边界观察效果很差。

以上是关于NSThread 内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章

c++ 内存泄漏问题

MFC内存泄漏调试

如何防止java中的内存泄漏

记录一次DialogFragment 内存泄漏

常见的内存泄漏原因及解决方法

Android ValueAnimator --内存泄漏