错误症状
最近做实训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函数重载
原文地址:https://www.jb51.cc/cocos2dx/342235.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。