由一个内存错误发现的cocos2dx 引擎3.4版本的 一个bug

由一个内存错误发现的cocos2dx 引擎3.4版本的 一个bug,第1张

概述错误症状 最近做实训cocos2dx项目的TA,一个同学在场景切换时遇到如下问题,场景B->C,C->B,B->C,然后场景C->B,返回场景B时程序就崩溃了 主要涉及代码 bool StartScene::init() { if (!Scene::init()) return false; MenuItemFont *skipMenuItem = 错误症状

最近做实训cocos2dx项目的TA,一个同学在场景切换时遇到如下问题,场景B->C,C->B,B->C,然后场景C->B,返回场景B时程序就崩溃了

主要涉及代码
bool StartScene::init() {      if (!Scene::init())        return  false;    MenuItemFont *skipMenuItem =           MenuItemFont::create("skip",this,menu_selector(StartScene::SkipMenuItemCallback));    skipMenuItem->setAnchorPoint(Vec2(0,0));    skipMenuItem->setposition(Vec2(900,25));    Menu *skipMenu = Menu::create(skipMenuItem,NulL);    skipMenu->setAnchorPoint(Vec2::ANCHOR_BottOM_left);    skipMenu->setposition(0,0);    this->addChild(skipMenu);    return true;

回调函数

voID StartScene::SkipMenuItemCallback(Ref* sender) {auto levelChosenScene = LevelChooseScene::createScene();Director::getInstance()->pushScene(levelChosenScene);}
bool LevelChooseScene::init() {    if (!Scene::init())        return  false;    CcmenuItemFont *levelChosenMenuItem = CcmenuItemFont::create("LevelChosen",menu_selector(LevelChooseScene::LevelChosenMenuItemCallback));    levelChosenMenuItem->setAnchorPoint(Vec2(0,0));    levelChosenMenuItem->setposition(Vec2(500,300));    Ccmenu *levelChosenMenu = Ccmenu::create(levelChosenMenuItem,NulL);    levelChosenMenu->setAnchorPoint(Vec2::ANCHOR_BottOM_left);    levelChosenMenu->setposition(0,0);    this->addChild(levelChosenMenu);    return true;}

点击回调函数:

voID LevelChooseScene::LevelChosenMenuItemCallback(Ref* sender) { Director::getInstance()->popScene(); }
错误定位

通过简单调试,发现startScene的引用计数异常,在一创建之后就为2,而在第二次pop之后变为0,而另外一个TA发现把startScene中的menuitem用CC_CALLBACK_1创建而不是menu_selector创建的话就没问题

MenuItemFont *skipMenuItem = MenuItemFont::create("skip",CC_CALLBACK_1(StartScene::SkipMenuItemCallback,this));

发现由原来的函数创建时:

bool MenuItemFont::initWithString(const std::string& value,Ref* target,SEL_MenuHandler selector){    CCASSERT( !value.empty(),"Value length must be greater than 0");    _target = target;    CC_SAFE_RETAIN(target);    return initWithString(value,std::bind(selector,target,std::placeholders::_1) );}

会维护了target指针,此例中就是StartScene指针
然后就是定位_target何时release(),

因为scene继承Ref,在Ref的release()函数中增加语句

if (!strcmp(typeID(*this).name(),"class StartScene"))    {        cclOG("hehe");    }

然后把断点设在cclOG处,观察堆栈帧

发现在menuitem::onExit()函数中

会realse()一次,导致了错误的发生
因为每次切换场景都对scene额外多realse()了一次,引擎的BUG在于不应该在menuitem中维护target指针

这个问题已经在最新版的cocos2dx引擎中解决了,新版本中不在提供menu_item 维护target指针的create函数重载

总结

以上是内存溢出为你收集整理的由一个内存错误发现的cocos2dx 引擎3.4版本的 一个bug全部内容,希望文章能够帮你解决由一个内存错误发现的cocos2dx 引擎3.4版本的 一个bug所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1064621.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-26
下一篇 2022-05-26

发表评论

登录后才能评论

评论列表(0条)

保存