iOS:为什么这个实例被解除分配?

时间:2012-01-03 07:56:21

标签: objective-c ios memory-management crash cocos2d-iphone

代码是:

if(!spriteInfoBack){
        spriteInfoBack = [CCSprite spriteWithFile:@"bg_player.png"];
        [spriteInfoBack setAnchorPoint:CGPointMake(0, 1)];
        [spriteInfoBack setPosition:CGPointMake(infoLeftX, infoTopY)];
        [parent addChild:spriteInfoBack];
}else{
        [spriteInfoBack setPosition:CGPointMake(infoLeftX, infoTopY)];
}

崩溃输出是:

[CCSprite setPosition:]: message sent to deallocated instance 0xc59cc70

它位于这一行:

[spriteInfoBack setPosition:CGPointMake(infoLeftX, infoTopY)];

我认为这很奇怪,因为if(!spriteInfoBack)已经检查过实例是否已取消分配。

3 个答案:

答案 0 :(得分:1)

您需要保留CCSprite。类方法spriteWithFile返回一个自动释放的对象。存储在spriteInfoBack中的返回值不归您所有。这意味着对象的生命周期直到下一个自动释放池耗尽。从您的代码中可以看出,您正在使用spriteInfoBack作为延迟初始化然后再使用的内容。您要做的是保留spriteWithFile的返回值,如下所示:

spriteInfoBack = [[CCSprite spriteWithFile:@"bg_player.png"] retain];

在将来的某个时候,您需要发布spriteInfoBack。我没有看到该类的其余部分,但如果spriteInfoBack是一个类的实例变量,那么在dealloc中这样做是有意义的。

答案 1 :(得分:0)

不,!spriteInfoBack只是检查nil的值(即:spriteInfoBlack == nil),这是不同的(如果你需要说服自己,请在{{1}中记录一些内容部分)。该变量仍然包含一个内存地址,因此崩溃,因为该实例已被释放。

我们无法通过查看实例被解除分配的代码来猜测,因此,一旦您不再需要它,请仔细检查代码,内存管理和/或将else放入变量中,这确保测试不会失败的方法。

答案 2 :(得分:0)

该实例位于自动释放池中,该池在ui的事件循环的迭代之间耗尽。如果希望对象在自动释放池中存活,则必须自己显式保留/释放对象。即使该对象已被释放(因为您尚未保留它),指针spriteInfoBack仍会记住该对象的旧地址。