升级到Lion并因此升级到XCode 4.1
运行分析仪时,我得到了数十个“潜在的内存泄漏”。
我通常会使用如下属性列表:
@synthesize indexPath = _indexPath;
- (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle {
self = [super initWithNibName:nibName bundle:nibBundle];
self.indexPath = [[NSIndexPath alloc] init];
[_indexPath release];
return self;
}
和dealloc()方法:
- (void)dealloc {
[_indexPath release];
[super dealloc];
}
现在,分析会告诉我self.indexPath上可怕的蓝色消息,告诉我有泄漏。什么时候显然没有。
如何分配和格式化代码,以便XCode不相信它会泄漏? (同时保留属性别名self.var vs _var)
谢谢...
答案 0 :(得分:8)
其他答案已经深入解释了这个问题,无论如何,这些是一些常用的模式可以用来避免这个错误:
NSIndexPath *ip = [[NSIndexPath alloc] init];
self.indexPath = ip;
/* ... */
[ip release];
的
indexPath = [[NSIndexPath alloc] init];
的
self.indexPath = [[[NSIndexPath alloc] init] autorelease];
的
self.indexPath = [NSIndexPath indexPathWithIndex:...];
答案 1 :(得分:6)
在init中你真的应该使用ivars直接设置:
- (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle {
self = [super initWithNibName:nibName bundle:nibBundle];
_indexPath = [[NSIndexPath alloc] init];
return self;
}
或许这可以解决这个问题?它将遵循惯例。
答案 2 :(得分:4)
问题在于,通过使用setter方法,编译器无法保证传递给setter的同一对象实际上将被分配给支持ivar。毕竟,你的setter方法可能会做各种奇怪的事情,其中最少的可能包括制作传递对象的副本。
换句话说,编译器无法保证self.indexPath == _indexPath
,因此您对release的调用可能与您从init
方法获得的对象不同。因此,它会向您发出警告,指出您的内存管理可能不正确,这是合适的。
因此,您需要保证在传递给setter的同一对象上调用release
。简而言之:
NSIndexPath *tmpPath = [[NSIndexPath alloc] init];
self.indexPath = tmpPath;
[tmpPath release]; // This is the only correct way to do it.
// [self.indexPath release]; // WRONG! May not be the same object as tmpPath
// [_indexPath release]; // WRONG! May not be the same object as tmpPath
正如其他人提到的那样,在init方法中,通常最好直接分配给ivar。因此:
_indexPath = [[NSIndexPath alloc] init];
答案 3 :(得分:2)
试试这个:
NSIndexPath *tmpPath = [[NSIndexPath alloc] init];
self.indexPath = tmpPath;
[tmpPath release];
答案 4 :(得分:2)
静态分析器可能只是在查看那一行,因为它不够聪明,没有意识到你实际上正试图纠正这个问题。
我会使用这种模式
NSIndexPath *tmpPath = [[NSIndexPath alloc] init];
self.indexPath = tmpPath;
[tmpPath release];
更深入的解释。因此,当分析仪查看该行
时self.indexPath = [[NSIndexPath alloc] init];
它看到这部分的+1保留
[[NSIndexPath alloc] init]
它看到self.indexPath
被编译为
[self setIndexPath:[[NSIndexPath alloc] init]];
此方法(如果由@synthesize
自动生成)可能看起来像这样
- (void)setIndexPathL(NSIndexPath *)indexPath
{
if (_indexPath != indexPath) {
[_indexPath release];
_indexPath = [indexPath retain];
}
}
现在分析器看到indexPath上还有另一个retain
。
所以这是2 x +1保留,它只能假设您将在dealloc中释放一次。