Got EXC_BAD_ACCESS error in ARC Enabled cocos2d Project?

184 views Asked by At

I followed the sample project from raywnderlich to venture into my first cocos2d application.

In that application moving targets are added like below

-(void)addMonster
{    
    __strong CCSprite * monster = [CCSprite spriteWithFile:@"monster.png"];
    CGSize winSize=[CCDirector sharedDirector].winSize;
    int minY=monster.contentSize.height/2;
    int maxY=winSize.height-minY;
    int rangY=maxY-minY;
    int actualY=(arc4random()%rangY)+minY;

    monster.position=ccp(winSize.width+monster.contentSize.width, actualY);
    [self addChild:monster];
    monster.tag=1;
    int minDuration=2.0;
    int maxDuration=4.0;
    int actualDuration=(arc4random()%(maxDuration-minDuration))+minDuration;

    CCMoveTo *actionMove=[CCMoveTo actionWithDuration:actualDuration
                                             position:ccp(-monster.contentSize.width/2, actualY)];
    CCCallBlock *actionDone=[CCCallBlock actionWithBlock:^(CCSprite *node){
        [node removeFromParentAndCleanup:YES];// crashed at this point
        [_monsters removeObject:node];

    }];
    [monster runAction:[CCSequence actions:actionMove,actionDone,nil]];
    [_monsters addObject:monster];
}

And I schedule the above method from -init method of my CCLayerColor subclass(scene) like below

-(id)init
{ 
    // player adding code
    [self schedule:@selector(gameLogic) interval:1.0];
}
-(void)gameLogic
{
    [self addMonster];
}

ie moving from left to right end of the ipad screen

My problem is that the application get crashed in the CCCallBlock while accessing the node object

Instead of downloading the source I planned to replicate the steps from the starting point but still can't find where it gets released. help me peers

Update:- I have posted the screenshots at the crash enter image description here enter image description here

2

There are 2 answers

1
CodeSmile On BEST ANSWER

The problem is quite simply that the block you're using doesn't conform to the expected interface. The CCCallBlock action expects a block with no parameters, but you defined the block as receiving a parameter (the node). I'm surprised that this even compiles. Of course the node passed in will be a garbage pointer and crash when accessed.

To fix this use CCCallBlockN whose block takes a CCNode* pointer as parameter:

CCCallBlockN *actionDone = [CCCallBlockN actionWithBlock:^(CCNode *node){
    // ...
    }];
3
in.disee On

Looks like the problem is about to much cleaning in actionDone.

You add monster to self (+1), 
add to array _monsters (+1), 
then remove [node removeFromParentAndCleanup:YES]; (-1), 
[_monsters removeObject:node]; (-1), 
[self removeChild:node]; (-1)
+2, -3 —> bad access

Also (in this particular case) you try to remove node two times, first by removeFromParentAndCleanup:, and then from parent removeChild:, select something one, you can't remove something two times