为什么在Objective-C中,在单独的语句中执行alloc和init会导致根据Xcode静态分析器释放对象?

Rob*_*ire 4 xcode memory-management objective-c

我正在使用Objective-C开始我的第一步,并且在XCode 4.1中遇到了一个轻微的问题,尽管是一个令人困惑的问题,即静态分析器(Product-> Analyze).我为有理数创建了一个简单的Fraction类,我分配并初始化为这样,

Fraction* f = [[[ Fraction alloc ] initWithNumerator:3 withDenomimator:5]
                                                               autorelease];
[ f print ];
Run Code Online (Sandbox Code Playgroud)

哪个printNSLog用于显示分数的方法,一切正常.但是,如果我将alloc/ initconstruct分成两个语句(我意识到这是非惯用的 - 我只是想了解机器)并使用手册release而不是autorelease给出:

Fraction* f = [ Fraction alloc ]; // 1. Method returns an Objective-C object with
                                  //    a +1 retain count (owning reference)
[ f initWithNumerator:3 withDenomimator:5]; // 2. Object released
[ f print ]; // 3. Reference-counted object is used after it is released
[ f release ];
Run Code Online (Sandbox Code Playgroud)

程序似乎仍然没有错误地运行,但XCode分析器在注释中给出了警告.为什么XCode认为init调用会导致对象被释放?

当我构思问题时,我可以看到我的两个程序并不完全相同,因为在第一个片段中,我的指针f是调用的结果,init而在第二个片段中,它是结果alloc.所以改变我的代码,

 Fraction* a = [ Fraction alloc ];
 Fraction* f = [ a initWithNumerator:3 withDenomimator:5];
[ f print ];
[ f release ]; // or should it be [ a release ] ?
Run Code Online (Sandbox Code Playgroud)

使它完全等效,静态分析仪停止抱怨.那么有可能init返回一个不同于传递给它的指针alloc,而不仅仅是配置已经传递的内存吗?有了这个代码,我应该配对[ a release ]使用alloc[ f release ]init

jus*_*tin 5

那么init是否可以返回与从alloc传递给它的指针不同的指针,而不仅仅是配置它已经传递的内存?

绝对.

使用此代码,我应该将[发布]与alloc或[f release]与init配对吗?

您可以将初始化对象的值分配给f(如您所示).此时,a可能是一个悬空指针(如果返回另一个地址).那f应该是released.

对此顺序的解释是该对象可能已选择返回其自身的专用版本/变体,并且此重新分配沿着init...链发生.

愚蠢的示威:

@interface Fraction : NSObject
{
@private
    int numerator;
    int denominator;
}

@end

static Fraction* EvilFraction = ...;

@implementation Fraction

- (id)initWithNumerator:(int)num denominator:(int)den
{
    self = [super init];
    if (nil != self) {
        if (0 == den){
            [self release];
            return [EvilFraction retain];
        }
    }
    return self;
}

@end
Run Code Online (Sandbox Code Playgroud)