Memory leaked hunting down -> How to call retain/release properly ?

I am trying to get used to manually call retain/release properly. But it seems I need help here.

From the figure with the blue highlight on one of the rows, that’s a memory leaked from using CCLabelTTF::labelWithString().
I would like to know the proper way release its when not use anymore.

FYI:
The testing game has 2 scene, one is for normal gameplay, and another is for showing a result. It will switch back and forth.
In addition, it’s weird that not every switching to another scene will generate the highlighted memory leaked (CCLabelTTF::labelWithString()). That label is static and normal to show some information in the game, so it will be used every time users play the game.

I use the code below for different case of those labels.

@
// create and initialize a label
CCLabelTTF* pLabel = CCLabelTTF::labelWithString(“Pew pew ~~”, “Thonburi”, 34);
// position the label on the center of the screen
pLabel~~>setPosition );
// add the label as a child to this layer
this~~>addChild(pLabel, 2);

// add special fire label
sprintf(m_specialNumUsageChars, “d/d”, m_numSpecialFire, NUM_SPECIAL_FIRE_USAGE);
m_specialFireNumUsageLabel = CCLabelTTF::labelWithString(m_specialNumUsageChars, “Thonburi”, 50);
m_specialFireNumUsageLabel~~>retain;
m_specialFireNumUsageLabel~~>setColor( ccc3(255, 0, 0));
m_specialFireNumUsageLabel~~>setPosition.y + 5));
this~~>addChild(m_specialFireNumUsageLabel, 2);

// add a counter of destroyed targets
sprintf(m_targetDestroyedCountChars, “%d”, _targetDestroyed);
m_targetDestroyedCountLabel = CCLabelTTF::labelWithString(m_targetDestroyedCountChars, “Thonburi”, 50);
m_targetDestroyedCountLabel~~>retain;
m_targetDestroyedCountLabel~~>setColor( ccc3(255, 0, 0));
m_targetDestroyedCountLabel~~>setPosition.width~~ 5,
m_specialFireButton->getPosition().y + 5));@

From the code above, we have 3 labels, the first one I didn’t call retain as I don’t interact with it during the gameplay session. But for another twos, I call retain() as I will change its string in real-time.
As well, when the game over I will switch to another scene and I did call release() explicitly before replacing the scene as well.

Anyway the code for releasing is still there in deallocate function just to make sure everything okay.

`HelloWorld::~HelloWorld()
{

if(m_specialFireNumUsageLabel)
{
    m_specialFireNumUsageLabel->release();
    m_specialFireNumUsageLabel = NULL;
}
if(m_targetDestroyedCountLabel)
{
    m_targetDestroyedCountLabel->release();
    m_targetDestroyedCountLabel = NULL;
}

}`

Sorry for a long post. But please help me to better understand how to handle the memory.
Thanks so much !


Screen Shot 2012-02-09 at 2.43.54 PM.png (100.9 KB)

Is the deconstructor from the class HelloWorld being called ? Try to release everything the “void onExit()” method (subclassing). I have found it is best to clean up there. At least for textures.

But in general what you call retain you call release afterwards and everything is ok! Guess you are checking this on the iOS Profiler ?

Thanks for your reply !

First of all, I’m checking this on iOS profiler via Instrument tool.

Answer your question below, …
Deconstructor never be called each switching of scene.
And thanks for your suggestion, I never used onExit() before and after use it, it works fine. I put up all necessary release stuff code inside it, and now I can get rid of those warning in the profiling.

Anyway, I can’t get rid of one warning, please take a look at the attached image.
It happens that the suspect code is as follows.

@
// gather the list of frames
CCMutableArray<CCSpriteFrame*> *walkAnimFrames = new CCMutableArray<CCSpriteFrame>;
for
{
// form a name
char name[HelloWorld::CHAR_BUFFER];
sprintf;
walkAnimFrames->addObject->spriteFrameByName);
}@
The first line of the code is what the tool suggest to look at.
**So the question is that. Did I properly create a new walkAnimFrames without calling retain ? Do I need to call it at all ?*

I even tested to call walkAnimFrames = NULL; after I don’t need it but it still not works.

Any suggestion ?

I dont store my frames on a mutable array, i use the way they used on exemples, even though i think your way is correct as well. Have you tried using “delete walkAnimFrames;” after you passed them to the animation ?

here is how i create my animations:

char frameName[100] = {0};

    CCAnimation *idleAnimation = CCAnimation::animation();

    for(int i = 0; i < 10; i++) {
        sprintf(frameName, "idle%01d.png", i);
        CCSpriteFrame *frame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(frameName);
        idleAnimation->addFrame(frame);
    }

    CCAnimate *idleAnimate = CCAnimate::actionWithDuration(0.5f, idleAnimation, false);
    idleAnim = (CCRepeatForever*)CCRepeatForever::actionWithAction(idleAnimate);
    idleAnim->setTag(kJogadorAnimacao_Idle);
    idleAnim->retain();

Oh, and on a side note, deconstructor methods are always called. onExit is just a bit before they are called. If your deconstructor is not getting called, you might be having leaks on your program. You should break before releasing everything and see where is heading.

Thanks so much !

I used your approach and it solved what’s left in memory leaked -> still pop up another ones but it’s for QuartzCore Lib’s responsibility which I don’t look into it.

I don’t think I will call “delete” for solving this problem, or another case, calling release() will automatically call “delete” inside. But anyway I’ve tried as your suggestion, but it won’t solve.
I’m not sure what’s the problem with my approach popping up memory leaked. Do you have any idea ?

Hey, there’s none issues left now. The last issue is because my mistake not to correctly check not to process anything after started to transition scene.
Thanks !

Really glad i could help! If you have any more questions please ask! Debugging and memory issues are a pain and hard to track down. You should worry about them from the very start. It will save a lot of headaches in the future! Good luck! :slight_smile:

My 20 copecks =)

What you should keep in mind: most of all (or even all) CC nodes and objects are inherited from CCObject. CCObject is a simple ref-counter object, so retain() incs ref-cnt, release() decs ref-cnt, once ref-cnt is 0, delete is called.
What does this involve - if someone (even CC itself) calls retain on your object, your call to release won’t delete it so you may need to track ref-cnt to clear things up.

As for nodes - once node is attached to parent (addChild), retain is called by CC. Once removed from parent (removeChild) - release is called. Also keep that in mind. So if you need to reuse your node after removal you should call node~~>retain before each parent~~>addChild(node) so that you node is not deleted after removeChild.

As for scene destructor - it’s called when you use CCDirector::sharedDirector()->replaceScene()/popScene() but is not called when pushScene(). This means your first scene should be always kept alive.

Not sure I completely understood your situation with static labels but if you need to pass data between scenes I would not recommend to use “retained” labels for that since it makes it harder to maintain. Instead I would suggest to use some single tone stats class that will keep game statistics for you.

Hope this helps.
Alex

PS: “Memory deallocation in Cocos2d-x / About NSAutoreleasePool in cocos2d-x / When should I invoke object->release()” section from FAQ (above in this forum) might be interesting to you.

Thanks for your information and suggestion, I think I better understand it now.