新浦京81707con > 软件下载 > x回收池原理,X内存管理机制

原标题:x回收池原理,X内存管理机制

浏览次数:96 时间:2019-11-14

cocos2d-x回笼池原理,cocos2d-x回笼

 

cocos2d-x源于cocos2d-iphone,为了与Objective-c黄金年代致,cocos2d-x也使用了引用计数与机关回笼的内部存款和储蓄器处理机制。

要切实可行自动内部存储器回笼,需后续于cocos2d-x的根类CCObject。当然自动释放会影响属性的。

 

cocos2d-x中有广大静态工场方法,比方以create初阶的,这个静态工场方法创造的对象都使用的autorelease,试想假设不用autorelease,

CCObject* create(){CCObject *ret = new CCObject(); return ret;}

当时函数内的援用在函数甘休时就得了了,然则对方并未有被假释,假如回去的ret未有被客商引用大概释放,那么就导致了内部存款和储蓄器败露。所以参加autorelease是个正确的解决办法。

 

拜谒CCObject的那三个字段和措施:

图片 1

protected:
    // 引用计数
    unsigned int        m_uReference;
    // 自动释放次数   以前是bool m_bManaged;标识是否采用自动释放
    unsigned int        m_uAutoReleaseCount;
public:
    void release(void);
    void retain(void);
    CCObject* autorelease(void);
    unsigned int retainCount(void);

图片 2

有这么三个法则:何人援引什么人retain和release,对象传值时先retain再release(制止本人给本人传值时,先release也许会自由对象卡塔尔,调用release方法,当援引计数为0时,就能delete此对象。

内部存款和储蓄器管理autorelease是怎么落到实处的呢,步入autorelease见到调用了下边这么些函数:

CCPoolManager::sharedPoolManager()->addObject(this);将对象参加回笼池

图片 3

void CCAutoreleasePool::addObject(CCObject* pObject)
{
    m_pManagedObjectArray->addObject(pObject);

    CCAssert(pObject->m_uReference > 1, "reference count should be greater than 1");
      (pObject->m_uAutoReleaseCount);
    pObject->release(); // no ref count, in this case autorelease pool added.
}

图片 4

函数元帅对象参与管理数组中,再对机关释放计数 1,然后release使引用计数-1。

当create一个对象时,new使援用计数为1,调用autorelease后,加入回笼池,然后release引用计数-1。那么那时引用计数为0呢?

答案自然不是,假如为0,那时该对象就能够被delete。cocos2d-x中的数据结构转为这种内部存款和储蓄器管理设置,如CCArray,当对array调用addObject时,就能够调用retain使引用计数加1,当array调用removeObject时就能release。那么当步向回笼池后,那时候的这一个引用归回笼池全体,当意气风发帧结束释放回笼池的时候,回笼池中的全部指标都会调用release。假如此刻一贯不任何对象援引该对象,则该对象会被剔除。

 

来探访主循环mainLoop中的调用:

图片 5

    if (m_bPurgeDirecotorInNextLoop)
    {
        m_bPurgeDirecotorInNextLoop = false;
        purgeDirector();
    }
    else if (! m_bInvalid)
     {
         drawScene();

         // release the objects
         CCPoolManager::sharedPoolManager()->pop();        
     }

图片 6

每生龙活虎帧停止调用sharedPoolManager()->pop()当时栈顶的回收池就被假释,

图片 7

void CCPoolManager::pop()
{
    if (! m_pCurReleasePool)
    {
        return;
    }

     int nCount = m_pReleasePoolStack->count();

    m_pCurReleasePool->clear();

      if(nCount > 1)
      {
        //释放栈顶的回收池
        m_pReleasePoolStack->removeObjectAtIndex(nCount-1);
        m_pCurReleasePool = (CCAutoreleasePool*)m_pReleasePoolStack->objectAtIndex(nCount - 2);
    }
}

图片 8

那时池中的全部目的都会被release,若无此外的对象(场景、层、数组等卡塔尔国在引用他们,那几个指标就能够被delete。

而新后生可畏帧开端后,第1个调用autorelease的对象在其间调用getCurReleasePool()时,假若栈中并未有回笼池,就能够push三个回笼池,sharedPoolManager()->push()。

图片 9

CCAutoreleasePool* CCPoolManager::getCurReleasePool()
{
    if(!m_pCurReleasePool)
    {
        push();
    }
    CCAssert(m_pCurReleasePool, "current auto release pool should not be null");
    return m_pCurReleasePool;
}

图片 10

 

 

 

能够看出每风流罗曼蒂克帧回笼池都要确立、删除,况且丰裕对象步向回笼池,那么质量方面本来会惨被震慑,当回收池中指标众多时,表现得很明显。

那么化解情势1:品质必要高的情事下不要自由使用自动回笼池。

 

办法2:手动释放并创建三个回笼池

CCPoolManager::shardPoolManager()->push();
for(int i=0; i!=n;   i)
{
     objArray[i]->autorelease();
}
CCPoolManager::shardPoolManager()->pop();

与此相类似就不会让机关释放的指标聚焦在风流洒脱帧停止的时候。

 

 

cocos2d-x源于cocos2d-iphone,为了与Objective-c风度翩翩致,cocos2d-x也选择了引用计数与机关回笼的内部存款和储蓄器管理机制。 要现...

转载:

Cocos2d-x 的内部存储器管理章程基于 Cocos2d-黑莓 的 Objective-C 风格的内部存款和储蓄器管理,把 Objective-C 的内部存款和储蓄器管理措施引进 C 。

 

1 复杂的内部存储器管理

C 设计上不分包别的智能处理内部存储器的体制,所以开垦进度中供给酌量怎么保管内部存款和储蓄器,富含:

  • 内存分红与回收的艺术和机会
  • 本着堆和栈做不一样的优化处理
  • 过火零散的指标分配回笼恐怕以致堆中的内部存款和储蓄器碎片化,降低内存的运用效能
  • 等等

内部存款和储蓄器管理的骨干是动态分配的指标必得确认保障在选择落成后有效性地释放内部存款和储蓄器,即管理对象的生命周期

明日看了一下cocos2dx的内部存储器管理体制,有个别地方不太好精晓搞了挺长的大运,现在感觉温馨掌握的非常多了,急迅写下团结的思绪和网络的大范围朋友分享,假若你意识有错误的地点依然不明了的地点接待指正!首先大家一定要说一下c 中变量的内存空间的分配难点,大家在c 中写三个类,能够在栈上分配内部存款和储蓄器空间也得以行使new在堆上分配内存空间,如若类对象是在栈上分配的内部存款和储蓄器空间,这么些内部存储器空间的治本就不是我们的事了,但黄金年代旦是在堆上分配的内部存款和储蓄器空间,当然需求我们来手动的delete了!cocos2dx选拔的是在堆上分配内部存款和储蓄器空间,用脑筋想看你在写程序的时候对于cocos2dx中的类是还是不是大多都是通过工厂方法得到的四个指南针,你见过在栈上分配内部存款和储蓄器空间的景象呢?所以难点来了,既然在堆上分配内存空间,那么什么样管理那几个内部存款和储蓄器空间,几时应该释放就是个难题了!在前后相继中,当大家创建了多少个对象的时候,那块内存空间经常是被区别的对象援引,要是去除的早了,有对象还在援用那块内部存款和储蓄器空间那么程序一定要崩溃!所以cocos2dx引进了引用计数那个内部存款和储蓄器处理机制。
当大家在堆上分配一块内部存款和储蓄器空间的时候,那一个目的的引用计数正是1,当有对象要援用那块内部存款和储蓄器空间的时候,那些援引计数就大增1,当有目的不再援引那块内部存款和储蓄器的时候援用计数就减1,当以此援引计数减为0的时候就应用delete删除掉那块内部存款和储蓄器,那样就完事了当有指标援引的时候会健康的拜谒那块内部存款和储蓄器,援用完成也得以平常的回笼。先来看一下之类的代码,有关援引计数的主题素材就能很掌握了!

2 现存的智能内存管理本事

一时,首要有三种达成智能管理内部存款和储蓄器的技巧,一是援用计数,一是酒囊饭袋回收

  • 援用计数:它通过给种种对象保证二个援用流量计,记录该对象当前被援引的次数。当对象扩展三回引用时,计数器加 1;而指标失去三遍援用 时,流速計减 1;当引用计数为 0 时,标识着该指标的生命周期甘休,活动触发对象的回笼释放

    引用计数的主要准则是每一个主次片段必需负权利地维护援用计数,在急需保险对象生活的程序段的起来和了结分别扩大和裁减二回援用计数,这样大家就能够实现足够灵活的智能内部存款和储蓄器管理了。

    实际,那与 new 和 delete 的交合使用极度像样,可是很奇妙地将转移和回收的平地风波转变来了使用和动用实现的事件。

    援用计数肃清了对象的生命周期管理难题,但堆碎片化和治本繁杂的难点依旧存在。

  • 污源回笼:它通过引入黄金时代种活动的内部存款和储蓄器回笼器,它会自行追踪每一个对象的有所援引,以便找到全体正在使用的指标,然后释放别的不再要求的靶子。

    污源回收器还是能减小使用中的内部存款和储蓄器,以压缩堆所须求的劳作空间。垃圾回笼能够堤防内部存款和储蓄器败露,有效地应用可用内部存款和储蓄器。可是,垃圾回笼器日常是充当贰个独自的低端别的线程运营的,在不可预见的景况下对内部存款和储蓄器堆中大器晚成度香消玉殒的要么长日子从没利用过的对象实行排除和回收,不能够手动指使垃圾回笼器回笼有些对象。

    回笼机制满含分代复制垃圾回收、标识垃圾回笼和增量垃圾回笼

?

3 Cocos2d-x的内部存款和储蓄器管理机制

Cocos2d-x采用了援引计数与活动回笼的内部存款和储蓄器管理机制

  • 为了促成目的的引用计数,封装了根类CCRef,别的具备类都派生自CCRef。
    /**
     * Retains the ownership.
     *
     * This increases the Ref's reference count.
     *
     * @see release, autorelease
     * @js NA
     */
    void retain();

    /**
     * Releases the ownership immediately.
     *
     * This decrements the Ref's reference count.
     *
     * If the reference count reaches 0 after the decrement, this Ref is
     * destructed.
     *
     * @see retain, autorelease
     * @js NA
     */
    void release();

    /**
     * Releases the ownership sometime soon automatically.
     *
     * This decrements the Ref's reference count at the end of current
     * autorelease pool block.
     *
     * If the reference count reaches 0 after the decrement, this Ref is
     * destructed.
     *
     * @returns The Ref itself.
     *
     * @see AutoreleasePool, retain, release
     * @js NA
     * @lua NA
     */
    Ref* autorelease();

    /**
     * Returns the Ref's current reference count.
     *
     * @returns The Ref's reference count.
     * @js NA
     */
    unsigned int getReferenceCount() const;
  • retain() 引用计数增 1,获取该指标的引用权

  • release() 令其援用计数值减 1,释放该对象的引用权

  • autorelease() 将对象放入当前机关回笼池(PoolManager::getInstance()->getCurrentPool()),当回笼池本身被释放 的时候,它就能够对池中的全数指标举行壹次release()方法,完成灵活的污源回笼。

  • getReferenceCount() 生命周期的引用计数值

  • 为了完结指标的自发性回笼,完结了CCPoolManager来管理AutoreleasePool对象池。

PoolManager* PoolManager::getInstance()
{
    if (s_singleInstance == nullptr)
    {
        s_singleInstance = new (std::nothrow) PoolManager();
        // Add the first auto release pool
        new AutoreleasePool("cocos2d autorelease pool");
    }
    return s_singleInstance;
}

AutoreleasePool::AutoreleasePool(const std::string &name)
: _name(name)
#if defined(COCOS2D_DEBUG) && (COCOS2D_DEBUG > 0)
, _isClearing(false)
#endif
{
    _managedObjectArray.reserve(150);
    PoolManager::getInstance()->push(this);
}
  • 老是主循环会释放回笼池PoolManager::getInstance()->getCurrentPool()->clear(),在下后生可畏帧初始前,引用计数值减 1,释放掉不在使用的靶子。
void Director::mainLoop()
{
    if (_purgeDirectorInNextLoop)
    {
        _purgeDirectorInNextLoop = false;
        purgeDirector();
    }
    else if (_restartDirectorInNextLoop)
    {
        _restartDirectorInNextLoop = false;
        restartDirector();
    }
    else if (! _invalid)
    {
        drawScene();

        // release the objects
        PoolManager::getInstance()->getCurrentPool()->clear();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//对象创建的时候引用计数被设置为1,这个是在它的构造函数中完成的,它会先调用父类CCOjbect的构造函数
    //CCObject的构造函数如下所示
    //CCObject::CCObject(void)
    //, m_uReference(1) {}// when the object is created, the reference count of it is 1
    CCSprite * sprite = new CCSprite();
 
    CCLog("retain count:%d",sprite->retainCount());
 
    //调用retain方法的时候引用计数增加1
    sprite->retain();
    CCLog("retain count:%d",sprite->retainCount());
 
    //调用release方法的时候引用计数减一,当这个引用计数减为0的时候,在release方法中会delete掉这个对象
    sprite->release();
    CCLog("retain count:%d",sprite->retainCount());
 
    //当我们调用autorelease方法的时候会调用这段代码
    //CCPoolManager::sharedPoolManager()->addObject(this);
    //调用autorelease方法的时候对象会被放到自动回收池中,这个自动回收池在每帧结束的时候会调用一次对象的release方法
    sprite->autorelease();
    CCLog("retain count:%d",sprite->retainCount());

4 工厂方法

厂子方法是前后相继设计中八个经文的设计情势,指的是基类中只定义创制对象的接口,将实际的贯彻推迟到子类中。在那处, 大家将它稍加推广,泛指一切生成并赶回叁个对象的静态函数。八个经文的厂子方法就如那样:

CCObject* factoryMethod()
{
    CCObject* ret = new CCObject();
 }

//在这里边对 ret 对象开展供给的最早化操作 return ret;
这段看起来不奇怪的代码其实掩饰着三个难题:工厂方法对ret对象的引用在函数重临时已经达成,但是它未有自由对ret 的援用,埋下了内存败露的祸患。然而,如若在函数再次来到前就执行release(),那明明是不切合的,因为那会接触对象的回收,再回来的对象指针就产生了不当指针。
autorelease()方法很好地解决了回收池中的对象不会在选拔完结前释放。利用 autorelease()修正后的工厂方法如下:

CCObject* factoryMethod()
{
    CCObject* ret = new CCObject(); //这里对 ret 对象进行必要的初始化操作
    ret->autorelease();
    return ret;
} 

上边包车型地铁代码有风流倜傥处不是很好的通晓,正是我们平常说的自发性回笼机制,也正是上边的autorelease方法,这几个法子到底为大家做了怎么,有何样效力,我们需求优质的搞驾驭!首先须要澄清的三个定义就是帧,大家平日的说每秒多少多少帧,其实那一个帧供给有些时间不是定位的,那么些须求看每帧大家需求做稍稍专门的学问,假诺没意气风发帧大家供给渲染相当多的东西,那那大器晚成帧实践的小时自然就能够十分短的,游戏体现就能很卡,那时每秒的帧率就能下落的,所以不是时控的帧率,而是帧影响的时日!这么些自动回笼池就是在每帧甘休的时候起效果的,在打闹的每一帧都会有三个大的循环,在豆蔻梢头帧开端早前,系统创设了四个内部存款和储蓄器回收池,在这里大器晚成帧的进程中,当大家调用了autorelease方法之后,大家的目的就能够放到这些内部存款和储蓄器回笼池中,当豆蔻年华帧甘休的时候这么些内部存款和储蓄器回笼池就会释放掉,这时候在内部存储器回笼池中的对象就能够被release一下,也便是说征引计数就能够减豆蔻梢头,要是这时引用计数为0,就能够删除对象了。如若引用计数不为0的话对象是不会被去除的,下风姿洒脱帧开端的时候系统又会创制一个内部存储器回笼池,这时在上三回加多的目的当时是不会另行增多到这么些内部存款和储蓄器回笼池中的,在这里个内部存款和储蓄器回笼池中的对象是你在此风度翩翩帧中调用了autorelease函数的指标。好了,内部存款和储蓄器回笼池小编觉的本身大器晚成度说明白了。下边大家来看一下,平时我们的代码都以怎么写的,来看看那一个活动回笼机制怎么就水到渠成自动回笼了!

5 关于目的传值

对象赋值给某一指南针作为引用的时,必要得到新对象的援引权,释放旧指标的引用权。当时,release()和 retain()的各样是尤其首要的。首先来看下面生龙活虎段代码:

void SomeClass::setObject(CCObject* other)
{ 
    this->object->release();
    other->retain();
    this->object = other;
}

?

6 释放:release()还是autorelease()?

  • autorelease()的垃圾池机制亟待占用内部存款和储蓄器和CPU能源,每便试行autorelease() 的历程,实际上对应的是推行成没错 retain()和 release(),甚至三次成没有错容器存取,还富含其余的逻辑剖断。

  • 过多不要求的autorelease()将导致垃圾池肥壮,在设有大气内部存款和储蓄器操作的顺序中进一层严重

  • autorelease()唯有在机关释放池被放出时才会实行三回释放操作,如果指标释放的次数超越了应当的次数,则这么些错误在调用 autorelease()时并不会被发觉,唯有当自动释放池被保释时(平时也等于娱乐的每黄金时代帧截至时),游戏才会崩溃。

本文由新浦京81707con发布于软件下载,转载请注明出处:x回收池原理,X内存管理机制

关键词: 新浦京81707con Cocos2dx 202.Cocos2d-

上一篇:STM32高级定时器TIM1产生两路互补的PWM波

下一篇:没有了