Cocos2d-x(Cocos引擎v1.0 Preview版) CSLoader 内存泄漏

本文探讨了在Cocos2d-x v1.0 Preview版本中使用CSLoader::create建立场景时出现的内存泄漏问题。通过对比三种不同场景创建方式,发现在加载CSB文件时由于资源的引用计数未正确处理导致内存占用持续上升。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用CSLoader::create建立场景,场景切换时内存会泄漏。
测试平台:Xcode 6.1 + iOS 8.2 + Cocos引擎v1.0 Preview版

新建工程时默认的HelloWorldScene.cpp,将Touch事件改为Clicked事件,在回掉中切换场景。

bool HelloWorld::init()
{
    if ( !Layer::init() )
    {
        return false;
    }
    auto rootNode = CSLoader::createNode("MainScene.csb");
    addChild(rootNode);
    auto closeItem = static_cast<ui::Button*>(rootNode->getChildByName("Button_1"));
    closeItem->addClickEventListener(CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
    return true;
}

void HelloWorld::menuCloseCallback(Ref* pSender)
{
    auto newScene = myScene::creatScene();
    Director::getInstance()->pushScene(newScene);
}

以下为测试用myScene类
myScene.h

#ifndef __playC2DX__myScene__
#define __playC2DX__myScene__

#include "cocos2d.h"

class myScene : public cocos2d::Layer
{
public:
    static cocos2d::Scene *creatScene();
    CREATE_FUNC(myScene);
    bool init();
    void onBnClicked(Ref *pSender);
};

myScene.cpp

#include "myScene.h"
#include "cocostudio/CocoStudio.h"
#include "ui/CocosGUI.h"

USING_NS_CC;
using namespace cocostudio::timeline;

Scene *myScene::creatScene()
{
    Scene *scene = Scene::create();
    myScene *layer = myScene::create();
    scene->addChild(layer);
    return scene;
}

bool myScene::init()
{
    Size win_size = Director::getInstance()->getWinSize();

// Test 1
//    auto bn = ui::Button::create("ipadhd/CloseNormal.png", 
//	 "ipadhd/CloseSelected.png", 
//	 "ipadhd/CloseNormal.png");
//    bn->setPosition(Vec2(win_size.width / 2, win_size.height / 2));
//    bn->addClickEventListener(CC_CALLBACK_1(myScene::onBnClicked, this));
//    addChild(bn);

// Test 2
//    auto sp = Sprite::create("ipadhd/CloseNormal.png");
//    sp->setPosition(Vec2(win_size.width / 2, win_size.height / 2));
//    addChild(sp);
//    auto listener = EventListenerTouchOneByOne::create();
//    listener->setSwallowTouches(true);
//    listener->onTouchBegan = [=](Touch* touch, Event* e) {
//        Point pos = sp->getPosition();
//        Size size = sp->getBoundingBox().size;
//        Rect rect = Rect(pos.x - size.width / 2, 
//	                   pos.y - size.height / 2, 
//	                   size.width, size.height);
//        pos = touch->getLocation();
//        if (rect.containsPoint(pos)) {
//            return true;
//        }
//        return false;
//    };
//    listener->onTouchEnded = [](Touch*, Event*) {
//        Director::getInstance()->popScene();
//    };
//    getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, sp);

// Test 3
    auto rootNode = CSLoader::createNode("SubScene.csb");
    addChild(rootNode);
    auto bn = static_cast<ui::Button*>(rootNode->getChildByName("Button"));
    bn->addClickEventListener(CC_CALLBACK_1(myScene::onBnClicked, this));
    return true;
}

void myScene::onBnClicked(Ref *pSender)
{
    Director::getInstance()->popScene();
}

        整个程序的效果就是点场景中唯一的按钮,利用pushScene与popScene切换场景,然后通过Xcode调试器观察内存使用变化。
        笔者照着两个场景中的场景切换按钮一阵狂点,切换N次场景后,Test1和Test2的内存占用都稳定的保持在16.5M,唯独Test3,场景每切换3次左右,内存占用就上升0.1M。
        该BUG是在笔者做一个实际项目时发现的,比起Test3,笔者的实际项目中,每切换2、3次场景内存占用就上升2M,笔者一阵狂点,内存占用轻松突破300M,对于内存配备仅1G的iPadMini2来说,这种泄漏是相当危险的。
        导致内存占用持续上升的原因是,在CSLoader中对资源进行了retain(),在随后的addChild()里,资源又被retain(),引用计数为2,但是在popScene()中资源只被release()一次,导致资源的引用计数最终变为1而不是0,占用内存自然不能被释放。
        据说Cocos2d-x v3.3RC2以后的版本已经解决这个问题,即在CSLoader中不进行任何的retain()动作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值