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:
隐式保留 object
和 cancel
隐式释放它。
您不必在主线程上保留object
以使其保持活动状态,以便为分离线程的缘故。
【讨论】:
还有其他原因我需要保留object
。但我也不确定这是否会有所帮助。当发布从我启动的线程发生时,它似乎搞砸了。
我进行了一些重构,以使object
不会持有太多东西,因此可以安全地随时释放它。我发现问题实际上在于object
正在抓住另一个正在观察自身的对象。根据一些研究,观察自我似乎不是一个好的模式。所以这可能是这里真正的解决方法,也是我最终要做的。尽管分解出 NSThread 特定的东西是合理的。感谢您的帮助。
我之前观察过self
,它可以工作,但是跨线程边界观察效果很差。以上是关于NSThread 内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章