[SOLVED]Problem about the memory management of cocos2dx

Hello!
I’m new to cocos2dx, and I’ve been in trouble with a memory problem.

I’m using Xcode to develop my game.And here is a part of my code:

bool MainMenuScene::init() {
    if (!Scene::init()) return false;
    auto audio = CocosDenshion::SimpleAudioEngine::getInstance();
    audio->playBackgroundMusic("res/HisotenSoku/bgm/op2.mp3", true);
    this->view = MainMenuViewLayer::create();
    this->opening = MainMenuOpeningLayer::create();
    this->ui = MainMenuUILayer::create();
    this->addChild(this->view);
    this->addChild(this->opening);
    auto listener = EventListenerTouchOneByOne::create();
    listener->onTouchBegan = [&](Touch* touch, Event* event) {
        if (this->hasEntered) {
            // ...
        } else {
            auto audio = CocosDenshion::SimpleAudioEngine::getInstance();
            audio->playEffect("res/HisotenSoku/se/061.wav");
            this->addChild(this->ui);
            this->removeChild(this->opening);
            this->hasEntered = true;
        }
        return true;
    };
    this->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);
    return true;
}

In MainMenuOpeningLayer, I’ve added some Sprites and Actions to display something like staff list and other information.What I need is when the player touches screen he can skip the display but do not remove the Sprites in MainMenuViewLayer.When I debugged the program, it showed “reference count should be greater than 0” at Ref::retain().

The wrong place is

this->addChild(this->ui);

in lambda expression.

Thus I think it is a memory problem and I tried this:

bool MainMenuScene::init() {
    if (!Scene::init()) return false;
    auto audio = CocosDenshion::SimpleAudioEngine::getInstance();
    audio->playBackgroundMusic("res/HisotenSoku/bgm/op2.mp3", true);
    this->opening = MainMenuOpeningLayer::create();
    this->addChild(MainMenuViewLayer::create());
    this->addChild(this->opening);
    auto listener = EventListenerTouchOneByOne::create();
    listener->onTouchBegan = [&](Touch* touch, Event* event) {
        if (this->hasEntered) {
            // ...
        } else {
            auto audio = CocosDenshion::SimpleAudioEngine::getInstance();
            audio->playEffect("res/HisotenSoku/se/061.wav");
            this->addChild(MainMenuUILayer::create());
            this->removeChild(this->opening);
            this->hasEntered = true;
        }
        return true;
    };
    this->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);
    return true;
}

This time it works as I expected.
So why the former will be crashed?Is it just because I didn’t use the Layer immediately after created and it was deleted by cocos2dx?
If so, how can I save a Node object from being deleted?

Thanks a lot. :blush:

Yes. When you create an object using its create method, it adds the object to something called the autorelease pool. At the end of each frame (I believe) the autorelease pool will check each object added to it to make sure it has a reference count of at least 1. If it does not, the object will be destroyed and removed from memory.

To increase the reference count to prevent the object from being destroyed, you have 2 main options. The first is to add the object to your scene, e.g. using the addChild function of a node already added to the scene. If you do not need to use that object yet after adding it to your scene, you can always use setVisible(false) on the object to hide it.

The other option is to use retain on the object. This simply increases the reference count by 1. Doing this will make sure the object isn’t destroyed by the autorelease pool, but you would need to remember to use release on the object once it is added to the scene or once the scene changes. If your scene changes while your object has that extra reference count, it will not be freed, and if you no longer have a variable pointing to that object, if you remain in memory until the app closes.

I think I will fall in love with the retain method :smile: Thanks