更新:此泄漏已经解决。如果您遇到类似的泄漏,并且您的应用程序是多线程的,那么您最有可能从后台线程进行UIKit调用;利用例如[NSThread performSelectorOnMainThread:]
将UIKit呼叫路由到主线程,这是 唯一可以允许的地方。
我最近在我目前的项目中运行泄漏以发现泄漏,并且我一直在遇到这些“泄漏”,据我所知,这些泄漏并非真正泄漏。根据Leaks的说法,以下代码直接来自项目,有两个漏洞:
- (NSArray *)areaForIndex:(int)index
{
NSMutableArray *a = [NSMutableArray arrayWithArray:
[world retrieveNeighborsForIndex:index]]; // leak 1
[a insertObject:[references objectAtIndex:index] atIndex:0];
return [NSArray arrayWithArray:a]; // leak 2
}
如果我将第一行更改为:,则泄漏1消失(参见更新2-3)
如果我将最后一行更改为:
,则泄漏2消失 return a;
我不能不幸地使用泄漏1,因为我正在将一个不可变数组转换为可变数组。不过,无论如何,arrayWithArray应该是自动释放的,所以从我所知道的,它不应泄漏任何东西。任何想法为什么会发生这种情况?
更新:我在设备和模拟器上都测试了这个。两者都有泄漏。但是,在模拟器上,我得到了一些关于此泄漏的其他信息:
泄漏的历史如下:
# | Category | Event Type | Timestamp | RefCt | Address | Size | Responsible Library | Responsible Caller
--+----------+-------------+
0 | CFArray | Malloc | 00:09.598 | 1 | 0x474f6d0 | 48 | asynchro | -[muddyGrid areaForIndex:]
1 | CFArray | Autorelease | 00:09.598 | | 0x474f6d0 | 0 | Foundation | NSRecordAllocationEvent
2 | CFArray | CFRetain | 00:09.598 | 2 | 0x474f7d0 | 0 | Foundation | -[NSCFArray retain]
3 | CFArray | CFRelease | 00:09.611 | 1 | 0x474f7d0 | 0 | Foundation | NSPopAutoreleasePool
我从上面可以看出的事情是,自动释放的数组以某种方式保留两次然后自动释放,保留计数为1.不知道在哪里或为什么......
更新2& 3:我尝试将Leak 1的行更改为:
NSMutableArray *a = [[[NSMutableArray alloc] initWithArray:
[world retrieveNeighborsForIndex:index]] autorelease];
我认为这样可以消除泄漏,但最终没有。所以我还是不知所措。
答案 0 :(得分:2)
通过猜测,这个问题解决了,因为我用我的代码解决了许多其他问题。
主要是,代码有很多地方在主线程之外进行UI更新,这是一个很大的禁忌。其中一个其他不相关的问题必须触发上述代码中的内存泄漏,因为它不再报告任何泄漏(我现在有0个泄漏),尽管我没有修改任何代码。
答案 1 :(得分:0)
retrieveNeighborsForIndex
会返回什么?
是否有可能保留此方法的结果(未自动释放)?
答案 2 :(得分:-1)
arrayWithArray保留存储在可变数组中的对象。 http://www.iphonedevsdk.com/forum/iphone-sdk-development/14285-nsmutablearray-arraywitharray-does-add-retain.html
我建议发布它,或者更安全但是创建具有autorelease属性集的对象。当为索引调用retrive邻居时,使这些对象自动释放,并且当nsmutable数组被释放时它们将被释放
编辑: 我可能在追踪内存错误时添加的一个提示是启用僵尸,并检查对象的引用计数。然后,您可以确定哪些未发布,并且应该使您的跟踪更容易。此链接将向您展示如何设置您的xcode项目以启用僵尸:cocoadev.com/index.pl?NSZombieEnabled