工程使用cocosBuilder后内存相关管理总结

最近几天把查了项目的内存泄漏问题,发现了些之前没想到问题,主要是引用后cocosBuilder导致的问题。

首先说下cocos2dx里面,基本的一些内存管理原则

1.每个CCObject对象在创建时 (eg: new CCObject ()), 它的引用计数为1,

2.它是autorelease的 (大部分情况下是这样的) 会在这一帧的结束时,被autorelease掉

3.CCNode对象的析构函数,会递归调用它所有孩子及子孩子的release, 对应在addChild时它们被调用的retain ()

4.所有手动调用retain () 的对象 (比如要保持住一个CCObject对象, 而它又不用被加到场景中去), 都要对应显示调用release ()

正常来讲,只要注意以上几点,项目中是不会出现内存问题,但在引用cocosBuilder后.会出现一些意想不到的事.

首先CCB_MEMBERVARIABLEASSIGNER_GLUE(...).

#define CCB_MEMBERVARIABLEASSIGNER_GLUE(TARGET, MEMBERVARIABLENAME, MEMBERVARIABLETYPE, MEMBERVARIABLE)     if (pTarget == TARGET && 0 == strcmp(pMemberVariableName, (MEMBERVARIABLENAME))) {         MEMBERVARIABLETYPE pOldVar = MEMBERVARIABLE;         MEMBERVARIABLE = dynamic_cast<MEMBERVARIABLETYPE>(pNode);         CC_ASSERT(MEMBERVARIABLE);         if (pOldVar != MEMBERVARIABLE) {             CC_SAFE_RELEASE(pOldVar);             MEMBERVARIABLE->retain();         }         return true;     }

用它来把ccb中的对象绑定到逻辑对象上时, 这个宏会把要绑定对象执行一次retain ().它是没有对应执行的release (), 这里如果不手工处理一下,会发现CCB里大量对象,在场景移除时,没有被解构

解决方法 1.在ccb资源的customClass的析构函数里, 对所以需要绑定的对象,执行一下release ()  eg:CC_SAFE_RELEASE_NULL (m_object).

    LoginShow_CCB()
    :CCLayer()

        ,m_menu(0)
        ,m_menuItem_exchangeUser(0)
        ,m_menuItem_exchangeServer(0)
        ,m_menuItem_enterGame(0)
        ,m_menuItem_binding(0)
        ,m_menuItem_reLogin(0)
        ,m_labelUserEmail(0)
        ,m_labelTip_email(0)
        ,m_labelServerName(0)
        ,m_labelTip_server(0)
        ,m_labelBundleVersion(0)
{}
virtual ~ LoginShow_CCB(){
//	CC_SAFE_RELEASE_NULL(m_menu);
//	CC_SAFE_RELEASE_NULL(m_menuItem_exchangeUser);
//	CC_SAFE_RELEASE_NULL(m_menuItem_exchangeServer);
//	CC_SAFE_RELEASE_NULL(m_menuItem_enterGame);
//	CC_SAFE_RELEASE_NULL(m_menuItem_binding);
//	CC_SAFE_RELEASE_NULL(m_menuItem_reLogin);
//	CC_SAFE_RELEASE_NULL(m_labelUserEmail);
//	CC_SAFE_RELEASE_NULL(m_labelTip_email);
//	CC_SAFE_RELEASE_NULL(m_labelServerName);
//	CC_SAFE_RELEASE_NULL(m_labelTip_server);
//	CC_SAFE_RELEASE_NULL(m_labelBundleVersion);
}

这里适合的情况是, 所有的绑定对象没有parent_child的所属关系.如果存在的话,和就上面提及到的第3条冲突了.有些结点就会重复release (),导致crash. 在C++里泄漏和crash只有一步之遥

解决方法 2.直接把宏里面的MEMBERVARIABLE->retain() 这句去掉,这种方式,暂时没发现问题

再一点,CCBAnimationManager::setAnimationCompletedCallback

如果需要在ccb的某一动作完成时,回调一个自定义方法,就会用到上面这句,这里也有一个坑,

void CCBAnimationManager::setAnimationCompletedCallback(CCObject *target, SEL_CallFunc callbackFunc) {
    if (target)
    {
        target->retain();
    }

    if (mTarget)
    {
        mTarget->release();
    }

    mTarget = target;
    mAnimationCompleteCallbackFunc = callbackFunc;
}

它个方法也会把CustomClass给retain (), 不注意的放,会有泄漏产生

解决方法 1. 在自定义的callBackFunc方法里,调用一下setAnimationCompletedCallback (NULL, NULL), 这种方式,要求每个callbackFunc都要记得写这句,(最后一个被回调的有用,但你不知道哪个最后调,所有都写最安全)

解决方法 2. 在customClass重写onExit (), 方法里写上这个setAnimationCompletedCallback (NULL, NULL), onExit方法千万别忘了写父类onExit eg: Parent::onExit, 不然有Touch注册的话,又是泄漏

另外,还有梅总之前发现的CCBReader对象,因为和customClass和循环依赖的问题, 要手动release掉.

关于CCBAnimationManager, 还有没有其它坑 (感觉还有,可能关系不大),有时间再研究一下,春哥要求赶紧总结下,以备方便他人

时间: 2024-10-20 21:11:40

工程使用cocosBuilder后内存相关管理总结的相关文章

C语言中内存的管理

一  Handler作用和概念 包含线程队列和消息队列,实现异步的消息处理机制,跟web开发的ajax有异曲同工之妙. 1.运行在某个线程上,共享线程的消息队列: 2.接收消息.调度消息,派发消息和处理消息: 3.实现消息的异步处理: Handler能够让你发送和处理消息,以及Runnable对象:每个Handler对象对应一个Thread和Thread的消息队列.当你创建一个Handler时,它就和Thread的消息队列绑定在一起,然后就可以传递消息和runnable对象到消息队列中,执行消息

驱动移植过程中DMA内存相关接口替换

1. 相关概念介绍及移植简介 1.1 物理地址与总线地址         1)物理地址是与CPU相关的.在CPU的地址信号线上产生的就是物理地址,在程序指令中的的虚拟地址经过段映射和页面映射后,就生成了物理地址,这个物理地址被放到CPU的地址线上.         2)总线地址,顾名思义,是与总线相关的,外设使用的就是总线地址.         在x86平台下,外设的I/O地址是独立的,即有专门的指令访问外设I/O,I/O地址就是所谓的"总线地址".而"物理地址"就

(笔记)Linux内核中内存相关的操作函数

linux内核中内存相关的操作函数 1.kmalloc()/kfree() static __always_inline void *kmalloc(size_t size, gfp_t flags) 内核空间申请指定大小的内存区域,返回内核空间虚拟地址.在函数实现中,如果申请的内存空间较大的话,会从buddy系统申请若干内存页面,如果申请的内存空间大小较小的话,会从slab系统中申请内存空间.有关buddy和slab,请参见<linux内核之内存管理.doc> gfp_t flags 的选项

Android 内存溢出管理与测试

今天发现正在做的项目,时不时的会报错:dalvikvm heap out of memory on a 7458832-byte allocation (堆分配的内存溢出) 为什么会内存溢出呢?我以前从未遇见这种情况.后来在网上查了查资料,还是挺多的. 怎么说呢?因为Android开发基本上是以java语言为基础,那么程序是在java虚拟机上运行的.而虚拟机不允许单个程序中的Bitmap占用超过8M的内存,从报错的日志可以看出:7458832-byte大约就是7M多的样子,基本吻合上述数据.在我

Sql Server 内存相关计数器以及内存压力诊断

在数据库服务器中,内存是数据库对外提供服务最重要的资源之一, 不仅仅是Sql Server,包括其他数据库,比如Oracle,MySQL等,都是一类非常喜欢内存的应用. 在Sql Server服务器中,最理想的情况是Sql Server把所有所需的数据全部缓存到内存中,但是这往往也是不现实的,因为数据往往总是大于可用的物理内存 可以说内存是否存在压力能够直接决定数据库能否高效运行,同时,如果内存出现压力,同时也会影响到CPU的使用和存储性能,可以说是一损俱损,具有连带性. 那么,如何识别内存是否

Linux 的内存分页管理

架构师必读:Linux 的内存分页管理 来源:Linux爱好者 ID:LinuxHub 内存是计算机的主存储器.内存为进程开辟出进程空间,让进程在其中保存数据.我将从内存的物理特性出发,深入到内存管理的细节,特别是了解虚拟内存和内存分页的概念. 内存 简单地说,内存就是一个数据货架.内存有一个最小的存储单位,大多数都是一个字节.内存用内存地址(memory address)来为每个字节的数据顺序编号.因此,内存地址说明了数据在内存中的位置.内存地址从0开始,每次增加1.这种线性增加的存储器地址称

[转帖]运维必读:Linux 的内存分页管理

运维必读:Linux 的内存分页管理 https://cloud.tencent.com/developer/article/1356431 内存是计算机的主存储器.内存为进程开辟出进程空间,让进程在其中保存数据.我将从内存的物理特性出发,深入到内存管理的细节,特别是了解虚拟内存和内存分页的概念. ▉内存 简单地说,内存就是一个数据货架.内存有一个最小的存储单位,大多数都是一个字节.内存用内存地址(memory address)来为每个字节的数据顺序编号.因此,内存地址说明了数据在内存中的位置.

JVM--Java内存相关

Java内存模型,Java内存管理,Java堆和栈,垃圾回收 本文是<成神之路系列文章>的第一篇,主要是关于JVM的一些介绍. 持续更新中 Java内存模型 细说Java多线程之内存可见性(视频)(推荐)(如果嫌视频讲的慢,建议使用1.5倍速度观看) JSR 133: JavaTM Memory Model and Thread Specification Revision(JMM英文官方文档) Java内存模型FAQ 深入理解Java内存模型(一)——基础 深入理解Java内存模型(二)——

Nginx 内存池管理

概述 Nginx 使用内存池对内存进行管理,内存管理的实现类似于前面文章介绍的<STL源码剖析--空间配置器>,把内存分配归结为大内存分配 和 小内存分配.若申请的内存大小比同页的内存池最大值 max 还大,则是大内存分配,否则为小内存分配. 大块内存的分配请求不会直接在内存池上分配内存来满足请求,而是直接向系统申请一块内存(就像直接使用 malloc 分配内存一样),然后将这块内存挂到内存池头部的 large 字段下. 小块内存分配,则是从已有的内存池数据区中分配出一部分内存. Nginx