我有一段Objective-C代码,如下所示:
- (NSString *)copyData:(NSData *)data
{
NSString *path = [[[self outputDirectory] stringByAppendingPathComponent:@"archive"] stringByAppendingPathExtension:@"zip"];
NSLog(@"Copying data to %@", path);
[data writeToFile:path atomically:NO];
return path;
}
从初始化程序调用代码,如下所示:
- (id)initWithData:(NSData *)data
{
if ((self = [super init]) != nil) {
NSString *path = [self copyData:data]; // Line 41 (referenced in warning, shown below)
return [self initWithContentsOfFile:path];
}
return self;
}
运行clang静态分析器时,我收到path
变量的以下警告:
第41行分配的对象的潜在泄漏并存储在'path'
中具有+0保留计数的对象返回给调用者,其中+1(拥有)保留计数
我很困惑。我的理解是stringByAppendingPathComponent
应该返回一个自动释放的字符串,所以应该的净保留计数为0.(显然我不希望保留它。)
我尝试更改copyData:
以返回以下内容,但它没有消除警告:
return [[path retain] autorelease];
那么这个警告的处理是什么?
答案 0 :(得分:15)
我怀疑它只是注意到一个前缀为copy
的方法,并将其标记为应返回调用者拥有的内容,因为它认为它遵循Cocoa命名约定。
在你的情况下,当然,你指的是文件和诸如此类的东西,所以这是一个可忽略的警告。如果您更改方法的名称,改为saveData:
,我打赌警告会消失。
答案 1 :(得分:9)
此外,对于您确实想要使用'copy'或其他方法命名方法的时间,因为无论Cocoa内存管理指南如何,copy都是该方法的最佳名称,您可以使用{{1}注释方法声明然后Clang不会给你一个警告。所以:
NS_RETURNS_NOT_RETAINED
答案 2 :(得分:4)
由于该方法中包含名称copy
,因此根据Memory Management Guide,分析器期望返回的对象具有+1保留计数。
答案 3 :(得分:4)
不,这是不正确的;除非方法包含“alloc”,“copy”,“new”或暗示该对象将由调用者拥有的其他关键字之一,否则该方法返回一个自动释放或以其他方式管理的对象,因此stringByAppendingPathComponent返回一个自动释放的字符串
除此之外,您的方法“copyData”包含单词“copy”,暗示调用者应拥有(并释放)结果。但是,您返回的结果已被自动释放,因此它会给您提供错误消息。如果要修复错误,请不要自动释放。那就是:
return [path retain]
当然这意味着你的函数的调用者需要释放它。或者,您可以更改功能的名称,使其符合内存管理准则。
恕我直言,名称“copyData”无论如何都是不直观的。我建议你将你的功能重命名为“pathToSavedDataWithData”等。有些东西说的是它实际上在做什么。
答案 4 :(得分:0)
我打算对此进行一次尝试,并猜测你会得到同样的错误信息,无论你的例程名称是否以“复制......”开头。我刚刚结束了类似的情况,“复制”不是我所调用的例程的名称的一部分。 Clang给出的错误信息仅仅是因为我正在返回一个自动释放的对象,这是一种危险的情况。做
return [path retain]
迈克尔推荐的最终技巧解决了这个问题。