如何修复此clang警告:“具有+0保留计数的对象返回给调用者,其中+1(拥有)保留计数”?

时间:2010-05-14 22:00:15

标签: objective-c cocoa clang clang-static-analyzer

我有一段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];

那么这个警告的处理是什么?

5 个答案:

答案 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]  
迈克尔推荐的最终技巧解决了这个问题。