Objective-C,释放一个物体两次?

时间:2011-04-03 17:02:35

标签: objective-c ios memory-leaks

我最近开始学习Objective-C 2.0,有一本书,我想知道我是否有这个概念。

所以这里是代码,它会导致释放未分配对象的错误:

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    Fraction *aFraction = [[Fraction alloc] init];
    Fraction *sum = [[Fraction alloc] init], *sum2;
    int n, i, pow2;

    [sum setTo: 0 over: 1];

    NSLog (@"Enter a value for n");
    scanf ("%i", &n);

    pow2 = 2;
    for ( i = 1; i <= n; ++i ) {
        [aFraction setTo: 1 over: pow2];
        sum2 = [sum add: aFraction];
        [sum release];
        sum = sum2;
        pow2 *= 2;
    }

    NSLog (@"After %i iterations, the sum is %g and the fraction is %i/%i.", n, [sum convertToNum], [sum numerator], sum.denominator);
    [aFraction release];
    [sum release];

    [pool drain];
    return 0;
}

我想知道sum和sum2。这是方法add:

- (Fraction *) add: (Fraction *) f
{
    Fraction *resultFraction = [[Fraction alloc] init];
    int resultNum, resultDenom;
    resultNum = numerator * f.denominator + denominator * f.numerator;
    resultDenom = denominator * f.denominator;

    [resultFraction setTo: resultNum over: resultDenom];
    [resultFraction reduce];

    return resultFraction;
}

让我解释一下我的想法。

对于循环的第一次迭代,分配sum,然后输入add:方法,并分配resultFraction。它返回sum2,这意味着resultFraction在返回后不会占用任何内存。

在循环之前分配的第一个总和将被释放sum = sum2,这意味着“{1}}中的对象现在”在“{1}}中,sum2在完成任务后没有任何记忆。接下来,分配一个新的sum并返回到sum2,直到现在这是免费的,依此类推,直到退出循环后释放sum。

现在只有一个对象(由resultFraction返回的对象),它只被分配给sum2 / add:(指针?或?)。但是,它不像我想的那样 - 当sum被分配一个新对象(由sum2返回的对象)并且没有被释放时,即使在将该对象分配给{{ 1}},前一个仍在那里。这意味着在n个赋值之后,将有n个对象“在”sum2中。因此,当我尝试在池排放之前释放add:sum时,我得到了错误。错误来自我尝试发布的第二个对象,我只能释放 sum2sum,因为它们都连接到{返回的最后一个对象{1}}方法?

我希望我足够清楚,因为我整天都在撞墙,而且它刚刚来到我身边,我真的希望我能做到这一点,所以我可以继续读这本书。 :)

1 个答案:

答案 0 :(得分:2)

那是什么书?这是一些明显非标准的内存管理模式。

首先,这个方法:

- (Fraction *) add: (Fraction *) f

应该返回一个自动释放的对象。目前不是。这导致调用方面的大量混淆,因为咒语不再是“如果你想保持一个对象返回值(超出NARC),你必须保留它”。

接下来,当您看到类似sum = sum2;的表达式(其中两个变量都是对象引用; Foo *)时,完全就像表达式x = 5;一样。这是一个简单的数字赋值;没有保留/释放暗示。

周四,如果你有:

sum = [[Fraction alloc] init];
sum2 = [[Fraction alloc] init];
sum = sum2;

你刚刚泄露了sum2所指的Fraction实例。所以:

  • 将保留/释放视为增量;你增加或减少计数。只要你的增加与你的减少完全平衡,你就是这样做的。

  • sum中的Fraction *sum;视为对象的潜在引用。宣布时,它什么都没有。当您将其分配给[[Fraction alloc] init];的结果时,没有魔法 - sum只保留内存中Fraction对象的地址。


你指的是这个吗?

    sum2 = [sum add: aFraction];
    [sum release];
    sum = sum2;

release释放旧sum,然后通过引用下一行的新对象覆盖该指针。

尝试构建并分析该代码。它会产生警告。这本书教你如何使用不泄漏的模式进行内存管理,但绝对不是标准的。我不相信沿着这条路走下去是有用的;现实情况是,总是在游戏中自动释放,因此,总是遵循系统的标准,即使是在你自己完全孤立的代码中也是如此。为什么花时间学习,然后不学习,在这一点上有不同的模式? (我全都是为了学习不同的模式和系统......只是不在这种情况下)。