初始化方法和“带有+0保留计数的对象返回给调用者,其中+1(拥有)保留计数是预期的” - 误报?

问题描述:

首先: 我明白了,为什么这个警告是存在的,我只是无法解释自己,为什么在这种情况下触发它。 官方Cocoa内存管理策略如下: “您拥有您创建的任何对象 您可以使用名称以”alloc“,”new“,”copy“或”mutableCopy“开头的方法创建对象(例如。,分配,NEWOBJECT,或mutableCopy)初始化方法和“带有+0保留计数的对象返回给调用者,其中+1(拥有)保留计数是预期的” - 误报?

您可以使用保留”

我知道有这样的代码的对象的所有权:

- (id) foo 
{ 
    // do something 
    return self; 
} 

- (id) init 
{ 
    self = [super init]; 
    return [self foo]; // clang static analyzer is complaining about returning an object with a +0 retain count here, although a +1 would be expected 
} 

据我所知,这是从铛假阳性,不是吗? 我的意思是,增加保留计数的唯一方法是“保留”和名称以“alloc”,“new”,“copy”或“mutableCopy”开头的所有方法,所以“init”不是增加保留计数,但在调用者上继续传递类​​“alloc” - 方法的返回值,所以实际上“init”预计会返回+0保留计数,而不是+1,不是吗?它只是返回具有相同保留计数的对象,并已传入该对象。 现在对该对象调用“foo”也不会更改保留计数,因此此代码应完全合法,实际上它工作正常并且在程序的整个生命周期内保留计数是正确的,只有静态分析仪在抱怨。

按照惯例方法名foo意味着它返回一个调用者不拥有的对象。

alloc - init***组合返回调用者拥有的对象。

看起来像分析仪不能或不想看看foo看看它实际在做什么,并不知道返回的值是与已有的self相同的对象。

这不是假阳性。如果一个子类,或者动态加载的类重写foo的返回别的东西:

- (id) foo; { 
    return [NSNumber numberWithInt:666]; 
} 

,那么你将有self泄漏和NSNumber对象的过度释放。

+0

据我所知富按照惯例只是意味着,它不会改变保留计数,同样喜欢初始化。约定在哪里陈述了关于必须在那里返回一个自动释放对象的事情? – Kaiserludi 2012-03-26 16:13:20

+1

@Kaiserludi它指定你是否拥有一个对象。你将一个你拥有的对象替换为另一个你不拥有的对象,除非它们是同一个对象,并且由于动态代码加载,否则在所有情况下显然都是错误的,你不能确定它永远是案子。对我来说似乎完全合理的行为。 – hamstergene 2012-03-26 17:14:01

+3

@Kaiserludi事实上,这里有两个问题:其一,你返回一个方法的标记结果(通过约定)返回一个非拥有对象(即返回[self foo])。这是编译器抱怨的错误。二,你从init方法中返回除self之外的东西,而不释放自己(即你正在泄漏自己)。foo写的方式,这两个错误(一个过度释放和一个泄漏)恰好相互抵消。 – jfortmann 2012-03-26 17:37:48

是的,这是一个误报,但在设计课程时这是一个不好的做法。 相反,你应该调用foo,然后回归自我,就像这样:

-(id) init 
{ 
    if ((self = [super init])) 
    { 
     [self foo]; 
    } 

    return self; 
} 
+1

请参阅hamstergene的回答,了解这不是假阳性。 – jfortmann 2012-03-26 17:31:10

+0

@jfortmann从我对OP的理解中,有关的选择器没有在头文件中定义,因此没有子类会知道覆盖它。 – 2012-03-26 19:03:00

+0

如果一个子类可能覆盖它,在这个实现中与编译器无关。与之相关的_only_是命名,对于-foo,它表示“此方法返回一个不属于调用者的值”。 – jfortmann 2012-03-28 18:42:19