Tuesday, March 27, 2012

Potential solution to EXC_BAD_ACCESS issue using CCLayer / CCNode

A recent problem I ran into, I was getting EXC_BAD_ACCESS issues when switching scenes in cocos2d. The problem was in the CCLayer's dealloc method. In particular this line (it may look a bit different in different versions of cocos2d):


- (void) dealloc {
...
    CCNode *child;
    CCARRAY_FOREACH(children_, child)
        child.parent = nil;
    [children_ release];
    [super dealloc];
}


OR


- (void) dealloc {
...
    for (CCNode *child in children_) {
        child.parent = nil;    
    }
    [children_ release];
    [super dealloc];
...
}


What it's basically doing is setting each child's (e.g., CCSprite) reference to its parent to nil and then releasing all the child objects from memory. What I was doing wrong was "fastidiously" releasing the child objects from CCLayer's dealloc method without thinking (I had declared them as instance variables of my CCLayer so I was then mindlessly releasing them in my dealloc method); then, when [super dealloc] is called in my CCLayer's dealloc method (which calls CCNode's dealloc method, since CCNode is CCLayer's superclass), there were no child objects to release since I already released them. Solution: remove my mindlessly written releases for the child objects from my CCLayer's dealloc method. High level points: (1) CCLayer will increase the retain count on objects you add as child objects (using the addChild: method), (2) CCLayer will clean up the child objects when CCLayer is deallocated.


It gave me a better understanding of memory management. Hope this helps someone.