引用计数的cocos2dx对象内存管理和直接new/delete box2d对象内存管理冲突的解决方法
来源:互联网 发布:java反编译怎么用 编辑:程序博客网 时间:2024/04/28 04:07
转载请注明: http://blog.csdn.net/herm_lib/article/details/9316601
项目中用到了cocos2dx和box2d,cocos2dx的内存是基于引用计数的,新建的内存一般加到一个自动的内存回收池中;而box2d的对象,是直接new/delete。
基于引用计数的对象和基于new/delete对象生命周期的结束是不一样的,前者有时比后者延后一帧(或者一个逻辑循环)才被删除。看一下实际遇到问题的代码。
class GameLayer : public cocos2d::CCLayer{public: GameLayer(); ~GameLayer(); static GameLayer* create();private: virtual void onEnter();private:// static b2World* m_phyWorld; b2World* m_phyWorld;};// b2World* GameLayer::m_phyWorld = nullptr;GameLayer::GameLayer(){ m_phyWorld = nullptr;}GameLayer::~GameLayer(){ delete m_phyWorld;}GameLayer* GameLayer::create(){ GameLayer* layer = new GameLayer; layer->autorelease(); return layer;}void GameLayer::onEnter(){ // 删除上一次进关卡生成的物理对象// delete m_phyWorld; m_phyWorld = new b2World(b2Vec2(0.0f, -10.0f)); MonsterSprite* monsterSprite = Monster::create(m_phyWorld);
addChild(monsterSprite); CCLayer::onEnter();}
GameLayer里生成一个b2World对象,同时也生成一个MonsterSprite 基于引用计数的对象,MonsterSprite是放到autorelease pool里,当GameLayer析构时removeChild, monster会被自动删除。再来看一下Monster做了什么。
class MonsterSprite : public cocos2d::CCSprite{private: b2World* m_phyWorld; b2Body* m_phyBody;};MonsterSprite* MonsterSprite::create(b2World* phyWorld){ MonsterSprite* monsterSprite = new MonsterSprite(phyWorld); MonsterSprite->autorelease(); return MonsterSprite;}MonsterSprite::MonsterSprite(b2World* phyWorld){ m_phyWorld = phyWorld; m_phyBody = phyWorld->CreateBody(...);}MonsterSprite::~MonsterSprite(){ m_phyWorld->DestoryBody(m_phyBody);}
代码看上去很清晰,貌似很正常。但跑起来,一般情况下,程序会在MonsterSprite::~MonsterSprite()的地方崩溃。我们分析一下,过程。
[1] 场景切换或者程序退出,GameLayer::~GameLayer()执行,这时候注意看delete m_phyWorld, b2World对象被删除;
[2] 执行CCLayer::~CCLayer(), 所有子节点被removeChild, MonsterSprite也被removeChild, MonsterSprite引用计数变为1了;
[3] 程序跑到下一帧,MonsterSprite被release, 执行MonsterSprite::~MonsterSprite,
m_phyWorld->DestoryBody(m_phyBody);
这个时候,m_phyWorld在上一帧就被删除了。
这种不同的内存管理方式,导致两个对象生命周期结束不一致。我想到了三种解决办法:
[1] 封装一下b2World,让的他内存管理方式和cocos2dx对象一致。
[2] MonsterSprite* monsterSprite = new MonsterSprite(phyWorld); 的时候,把monsterSprite保存起来,在GameLayer::~GameLayer()中,手动把monsterSprite中的b2Body 清除,不要等到析构的时候删除。
[3] 请看代码注释的地方,把b2World的生命周期拉长,GameLayer退出的时候,不删除;再次进入GameLayer的时候删除。这样做不会有内存泄露,也最简单。
- 引用计数的cocos2dx对象内存管理和直接new/delete box2d对象内存管理冲突的解决方法
- 手动内存管理-对象的引用计数
- Cocos2dx对象的内存管理0
- Cocos2dx 对象的内存管理1
- Cocos2dx 对象的内存管理2
- Cocos2dx对象的内存管理3
- Python的内存管理、对象的引用
- Box2D 内存管理 - 小型对象分配器(SOA)的实现
- Box2D 内存管理 - 小型对象分配器(SOA)的实现
- 内存管理:new和delete
- new和delete管理内存
- Cocos2dx内存管理之引用计数分析
- 对象的内存管理
- C++的new、delete及其内存管理
- C++的动态内存管理,new/delete
- OC的内存管理 与 引用计数
- OC使用引用计数的内存管理
- OC的内存管理引用计数机制
- 第一周CF
- KMP详解
- memcache与mysql数据库同步
- 友情链接很重要 不过交换的时候要睁大眼睛了
- 纠结的float和unsigned char
- 引用计数的cocos2dx对象内存管理和直接new/delete box2d对象内存管理冲突的解决方法
- 凤凰视频和优酷视频都改版 视频行业要有意思了
- 多核 vs 多线程:合适的才是最好的
- JAVA MAIL发送邮件实例
- 暑期规划
- Lua程序设计笔记一: 基础用法/类型与值
- 多核多线程技术编程
- ios定位服务详解
- 算法--中位数计算