Memory Leaks

Hi,

So I started profiling my game against memory leaks. I found a tool called visual leak detector and it is outputting that I have some memory leaks. From what I see I think I am managing everything correctly on my end. Here is what I do:

Inside my game Init I initialize 50 game object and store them inside a CCArray and these game object pretty much just have a sprite and some additional info on whether or not they are active (visible) or not. This is what it looks like:

mNodes = new CCArray();

for(int i = 0; i < Constants::TOTAL_OBJECTS; ++i)
{
        CCSprite* spr = CCSprite::createWithSpriteFrameName("GameNode.png");

        GameObject* gameNode = new GameObject();
    gameNode->Init(spr, 0, this);

    gameNode->autorelease();

    gameNode->SetObjectPosition(m_ccVisibleSize.width*0.5f, m_ccVisibleSize.height*0.5f);

    mNodes->addObject(gameNode);
}

My game object’s init and destructor looks like this:

GameObject::~GameObject()
{
    CCLOG("GameObject::~GameObject");
}

void GameObject::Init(CCSprite* sprite, CCSprite* shadow, CCLayer* layer)
{
    mCurrentSpeed = 1.0;
    mSpawnSpeed = 1.0;
    m_fSpeedFactor = CCDirector::sharedDirector()->getVisibleSize().height / 480.0f;

    Object::Init(sprite, shadow, layer);
}

Object::~Object()
{

}

void Object::Init(CCSprite* sprite, CCSprite* shadow, CCLayer* layer)
{
    mSprite = sprite;

    layer->addChild(sprite);

    SetState(kInActive);

    mHalfWidth = mSprite->getContentSize().width * 0.5f;
    mHalfHeight = mSprite->getContentSize().height * 0.5f;

    mRect = CCRectMake(mSprite->getPosition().x - mSprite->getContentSize().width*0.5, 
                       mSprite->getPosition().y - mSprite->getContentSize().height*0.5, 
                       mSprite->getContentSize().width, 
                       mSprite->getContentSize().height);

}

Object::~Object()
{

}

void Object::Init(CCSprite* sprite, CCSprite* shadow, CCLayer* layer)
{
mSprite = sprite;

layer~~>addChild;
SetState;
mHalfWidth = mSprite~~>getContentSize().width * 0.5f;
mHalfHeight = mSprite~~>getContentSize.height * 0.5f;
mRect = CCRectMake.x~~ mSprite~~>getContentSize.width*0.5,
mSprite~~>getPosition().y - mSprite~~>getContentSize.height*0.5,
mSprite~~>getContentSize().width,
mSprite~~>getContentSize.height);
}
</pre>
Keep in mind the object class has a cocos2d::CCSprite and I add this to the game scene by passing a pointer to the game scene in the init.
Here is the game scene destructor:
<pre>
GameScene::~GameScene
{
CCLOG (“GameScene::~GameScene()”);
if)
{
setTouchEnabled;
}
this~~>unschedule(schedule_selector(GameScene::Countdown));
this~~>unschedule);
this~~>unschedule(schedule_selector(GameScene::GenObj));
this~~>unschedule);
this~~>unscheduleAllSelectors();

CCNotificationCenter::sharedNotificationCenter()>removeObserver;
CCNotificationCenter::sharedNotificationCenter
>removeObserver;
if
{
mNodes~~>release;
mNodes = 0;
}
}
</pre>
I have also attempted to do this right before releasing the mNodes array:
<pre>
CCObject* jt;
CCARRAY_FOREACH
{
Object *node = static_cast<Object*>;
mNodes~~>removeObject(node);
this~~>removeChild, true);
if
{
node~~>release();
node = 0;
}
}

But the game breaks and I get one of these HEAP: Free Heap block 06E2FE18 modified at 06E2FE4C after it was freed :S

Lastly here is what VLD (visual leak detector) reports:

WARNING: Visual Leak Detector detected memory leaks!
---------- Block 514 at 0x01D34CB8: 240 bytes ----------
  Call Stack:
    c:\development\cocos2d-2.0-x-2.0.4\game\classes\gamescene.cpp (305): Game.win32.exe!GameScene::init + 0xA bytes
    c:\development\cocos2d-2.0-x-2.0.4\game\classes\gamescene.h (136): Game.win32.exe!GameScene::create + 0xB1 bytes
    c:\development\cocos2d-2.0-x-2.0.4\game\classes\gamescene.cpp (174): Game.win32.exe!GameScene::scene + 0x5 bytes
    c:\development\cocos2d-2.0-x-2.0.4\game\classes\appdelegate.cpp (76): Game.win32.exe!AppDelegate::applicationDidFinishLaunching + 0x5 bytes
    c:\development\cocos2d-2.0-x-2.0.4\cocos2dx\platform\win32\ccapplication.cpp (47): libcocos2d.dll!cocos2d::CCApplication::run + 0xF bytes
    c:\development\cocos2d-2.0-x-2.0.4\game\proj.win32\main.cpp (38): ColorShift.win32.exe!wWinMain + 0x19 bytes
    f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (528): Game.win32.exe!__tmainCRTStartup + 0x15 bytes
    f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (377): Game.win32.exe!wWinMainCRTStartup
    0x76588543 (File and line number not available): KERNEL32.DLL!BaseThreadInitThunk + 0xE bytes
    0x77CCAC69 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x85 bytes
    0x77CCAC3C (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x58 bytes
  Data:
    18 D6 1B 01    4B 0C 00 00    00 00 00 00    01 00 00 00     ....K... ........
    00 00 00 00    30 4A D3 01    01 00 00 00    E8 53 44 0F     ....0J.. .....SD.
    4C 0C 00 00    00 00 00 00    01 00 00 00    00 00 00 00     L....... ........
    00 00 A0 43    00 00 F0 43    00 00 90 41    00 00 90 41     ...C...C ...A...A
    FC 53 44 0F    4D 0C 00 00    00 00 00 00    01 00 00 00     .SD.M... ........
    00 00 00 00    D4 53 44 0F    4E 0C 00 00    00 00 00 00     .....SD. N.......
    01 00 00 00    00 00 00 00    00 00 61 43    00 00 24 C2     ........ ..aC..$.
    E8 53 44 0F    4F 0C 00 00    00 00 00 00    01 00 00 00     .SD.O... ........
    00 00 00 00    00 00 10 42    00 00 10 42    00 00 26 43     .......B ...B..&C
    00 00 80 3F    00 00 26 43    76 98 FB 43    E9 FF FF FF     ...?..&C v..C....
    01 00 00 00    60 87 B9 C1    00 00 00 00    6F 12 03 3B     ....`... ....o..;
    00 00 00 00    00 00 CD CD    D4 53 44 0F    50 0C 00 00     ........ .SD.P...
    00 00 00 00    01 00 00 00    00 00 00 00    00 00 00 00     ........ ........
    00 00 00 00    D4 53 44 0F    51 0C 00 00    00 00 00 00     .....SD. Q.......
    01 00 00 00    00 00 00 00    00 00 00 00    00 00 00 00     ........ ........

This is just one object it goes on for another 50.

Any help would be amazing as I spent a day trying to get this straightened out with no luck it seems.

Thanks,
J

I made some modifications to the code above to what I think should be the correct way to allocate and deallocate the memory. The game object is still the same setup as noted above. The changes I made is in GameScene::Init() and GameScene::~GameScene(). Here are the changes:

mNodes = CCArray::createWithCapacity(Constants::TOTAL\_OBJECTS);//new CCArray(); mNodes~~\>retain; for { CCSprite\* spr = CCSprite::createWithSpriteFrameName; GameObject\* gameNode = new GameObject; gameNode~~\>Init(spr, 0, this);

gameNode~~>retain;//~~>autorelease();

gameNode~~>SetObjectPosition;
mNodes~~>addObject(gameNode);
}

CCObject* jt; CCARRAY_FOREACH(mNodes, jt) { Object *node = static_cast(jt); //mNodes->removeObject(node); if(node) { node->release(); node = 0; } }
if(mNodes)
    {
        mNodes->release();
        mNodes = 0;
    }

This is what I think it should be after reading some online references but I still get leaks reported doing this also triggers a heap violation in Visual studio :
HEAP: Free Heap block 03DAAC68 modified at 03DAAC9C after it was freed.

Any ideas???

thanks!

  1. CCArray will retain any object put into and release it after CCArray gets destroyed. You don’t need any FOREACH releasing objects in CCArray.
  2. An object created with new() has refcount = 1. You don’t need to retain it once more. Just release it after you’ve put it into CCArray or saved somewhere else.

PS Here’s good description on how it works [[Memory Management in Cocos2d-x]].

Thanks a lot Igor for your reply. I ended up making those adjustments and and a few others, this has solved all of my issues.

Thanks again!:slight_smile: