我有这样的代码:
- (CGImageRef)createImageWithContext:(CGContextRef)context
{
return CGBitmapContextCreateImage(context);
}
- (void)fooWithContext:(CGContextRef)context
{
CGImageRef imgRef = [self createImageWithContext:context];
CGImageRelease(imgRef);
}
这是一个在Xcode中使用ARC构建的Objective-C项目。Build and Analyze报告了两个错误:一个在CGBitmapContextCreateImage行上,识别潜在的泄漏,另一个在cgimagerrelease上,注意到"不正确地减少了调用者此时不拥有的对象的引用计数"。
如果我将这两个函数合并为一个:
- (void)fooWithContext:(CGContextRef)context
{
CGImageRef imgRef = CGBitmapContextCreateImage(context);
CGImageRelease(imgRef);
}
我没有收到任何警告。
静态代码分析bug?还是我遗漏了什么?
根据标准的Cocoa命名约定,以单词create
开头的方法应该返回一个非所有的引用。您正在返回一个保留的对象,但是您期望返回一个非保留的对象。因此,当分析器查看-createImageWithContext:
时,它看到假定返回非保留对象,但实际上返回的是保留对象。这就是第一个警告。
在-fooWithContext:
中,它查看您的代码并说"嘿,根据我的命名约定,createImageWithContext:
应该返回一个非拥有的引用。但他们释放了不属于他们的东西!那就糟糕了!"因此出现了第二个警告。
您可以通过将-createImageWithContext:
的名称更改为以new
开头的名称来解决此问题,例如-newImageWithContext:
。或者您可以用cf_returns_retained
宏注释该方法,以向静态分析器指示该方法正在返回一个所属引用。
我想这是一个"假阳性",这真的很有意义:
分析器不知道createImageWithContext:
中的返回值必须被释放(您可以在其他地方调用createImageWithContext:
,然后不执行CGImageRelease
),也不知道fooWithContext:
中的imgRef
已被正确保留。
我的2美分