转载请注明: 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是一个cocos2d对象,他回创建b2Body, 在析构的时候,将这个body从b2World中删除。

代码看上去很清晰,貌似很正常。但跑起来,一般情况下,程序会在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对象内存管理冲突的解决方法的更多相关文章

  1. Cocos2d-x 3.2编译生成Android程序出错Error running command, return code: 2的解决方法

    用Cocos2d-x 3.2正式版创建项目,结果使用cocos compile -p android编译生成APK程序,结果悲剧了,出现以下错误. Android NDK: Invalid APP_S ...

  2. 关于Cocos2d-x中掉帧导致游戏一卡一卡的网上一些的解决方法

    方法1 掉帧主要是setpostion引起的  因为每一帧每一个精灵都要set一次虽然不知道为什么会这样但是if(poX<1000&&pox>-100){     xx-& ...

  3. iOS内存管理系列之一:对象所有权与引用计数

    当一个所有者(owner,其本身可以是任何一个Objective-C对象)做了以下某个动作时,它拥有对一个对象的所有权(ownership): 1. 创建一个对象.包括使用任何名称中包含“alloc” ...

  4. Objective-C内存管理之引用计数

    初学者在学习Objective-c的时候,很容易在内存管理这一部分陷入混乱状态,很大一部分原因是没有弄清楚引用计数的原理,搞不明白对象的引用数量,这样就当然无法彻底释放对象的内存了,苹果官方文档在内存 ...

  5. OC基础15:内存管理和自动引用计数

    "OC基础"这个分类的文章是我在自学Stephen G.Kochan的<Objective-C程序设计第6版>过程中的笔记. 1.什么是ARC? (1).ARC全名为A ...

  6. cocos2D-x 3.5 引擎解析之--引用计数(Ref),自己主动释放池(PoolManager),自己主动释放池管理器( AutoreleasePool)

    #include <CCRef.h> Ref is used for reference count manangement. If a classinherits from Ref. C ...

  7. 初步swift语言学习笔记6(ARC-自己主动引用计数,内存管理)

    笔者:fengsh998 原文地址:http://blog.csdn.net/fengsh998/article/details/31824179 转载请注明出处 假设认为文章对你有所帮助.请通过留言 ...

  8. swift内存管理中的引用计数

    在swift中,每一个对象都有生命周期,当生命周期结束会调用deinit()函数进行释放内存空间. 观察这一段代码: class Person{ var name: String var pet: P ...

  9. iOS内存管理机制解析之MRC手动引用计数机制

    前言: iOS的内存管理机制ARC和MRC是程序猿參加面试基本必问的问题,也是考察一个iOS基本功是 否扎实的关键,这样深入理解内存管理机制的重要性就不言而喻了. iOS内存管理机制发展史 iOS 5 ...

随机推荐

  1. java的loadrunner脚本案例

    /* * LoadRunner Java script. (Build: 670) *  * ״̬£º²¢·¢²âÊÔͨ¹ý * ²âÊÔÈË£ºÕÔС±ò * ÈÕÆÚ£º2013-09-2 ...

  2. Mybatis的初步使用

    MyBatis 是当下最流行的持久层框架,也是ORM框架,本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google ...

  3. VMW虚拟机生成的文件说明

    VMDK(VMWare Virtual Machine Disk Format)是虚拟机VMware创建的虚拟硬格式,文件存在于VMware文件系统中,被称为VMFS(虚拟机文件系统) NVRAM 非 ...

  4. FreeMarker使用之比较if

    1. =或者==:判断两个值是否相等. 2. !=:判断两个值是否不等. 3. >或者gt:判断左边值是否大于右边值 4. >=或者gte:判断左边值是否大于等于右边值 5. <或者 ...

  5. 一张图解AlphaGo原理及弱点

    声明:本文转载自(微信公众号:CKDD),作者郑宇 张钧波,仅作学习收录之用,不做商业目的. 近期AlphaGo在人机围棋比赛中连胜李世石3局,体现了人工智能在围棋领域的突破,作为人工智能领域的工作者 ...

  6. jmeter-----用户参数和用户定义变量的区别

    在调试脚本的时候,可以使用前置处理器中的用户参数组件进行数据的提供,在该数据中可以使用固定值也可以使用变量值. 如果是固定不变的一些配置项,不需要多个值的时候,也可以使用用户已定义的变量组件. 一.界 ...

  7. html5.2新特性【长期更新】

    先来说几个新定义: 1.p标签里只能是文字内容,不能在里面使用浮动,定位这些特性了.语义化加强,p标签就是文字标签. 2.legend以前只能是纯文本,新版可以加标签了,很爽吧. <fields ...

  8. 【WPF】Bitmap Effect制作圆角加渲染TextBox

    <Window.Resources> <ControlTemplate x:Key="txtTemplate" TargetType="{x:Type ...

  9. hihocoder 1497 Queen Attack

    排序. 分别按照$x$,$y$以及对角线排序,统计一下方案数就可以了. #include<bits/stdc++.h> using namespace std; int n; struct ...

  10. mongodb 32系统安装失败问题

    32位系统 在安装完成后 运行mongod --dbpath c:\data\db后,没有如愿以偿出现端口数字27017,出现了如下的报错 ************** D:\GREENT~1\Pow ...