由一个内存错误发现的cocos2dx 引擎3.4版本的 一个bug
来源:互联网 发布:重庆优化公司哪家好 编辑:程序博客网 时间:2024/05/16 10:28
错误症状
最近做实训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", this, 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函数重载
0 0
- 由一个内存错误发现的cocos2dx 引擎3.4版本的 一个bug
- 由ORA-00979错误发现ORACLE一个BUG
- cocos2dx AssetsManager的一个BUG
- cocos2dx AssetsManager的一个BUG
- 发现CSDN的一个Bug
- 发现一个jet2的bug
- 发现hotmail的一个bug
- 发现Chrome的一个bug
- 发现一个csdn的bug
- 发现CSDN的一个Bug
- 发现csdn的一个bug
- 发现淘宝的一个bug
- 发现一个gcc的“BUG”?
- 发现一个gccxml的bug!
- 发现CSDN的一个BUG
- 发现eval的一个BUG
- 由一个BUG想到的
- 由一个bug想到的
- cocos2d-x游戏开发(五)神奇的自动释放
- uva 1291(dp)
- SessionFactory.getCurrentSession与openSession的区别
- 同一进程内 Bind方式的意义
- cocos2d-x游戏开发(六)自动释放池
- 由一个内存错误发现的cocos2dx 引擎3.4版本的 一个bug
- 单例模式(java)
- android webview响应web页面js
- The HealthKit Framework
- 关于Git的入门理解以及第二天实习收获
- cocos2d-x游戏开发(七)对象释放时机
- 实现相册的缩放图片功能
- URAL 1996 Cipher Message 3 FFT + KMP
- oracle 定时任务