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.
- (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.
Hey Mark thanks for the help. I was struggling with the same problem! I had released some CCSprites on my own and couldn't figure out what was going on. I did some more research on memory management and found that Cocos2d takes care of most of it through the code above and methods like [myLayer removeChild:myObject] that automatically clean up memory for you. Anyway, not sure if you're still a blogger here, but want you to know this did help someone!
ReplyDeleteHey, glad it helped. Hope your memory management skills are much better now!
Delete