加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

cocos2dx - ActionManager内存泄露

发布时间:2020-12-14 16:38:04 所属栏目:百科 来源:网络整理
导读:ActionManager memory leak cocos2d-x3.7 都3.7了还有这样的bug,真是好难过,不过还是好开源的,谁都可以贡献一下 问题描述: 当创建一个node,并让它run一个action的时,如果这个node没有添加到任何其它节点(即没有父节点),那么改node和action将一直不

ActionManager memory leak

cocos2d-x3.7


都3.7了还有这样的bug,真是好难过,不过还是好开源的,谁都可以贡献一下

问题描述:

当创建一个node,并让它run一个action的时,如果这个node没有添加到任何其它节点(即没有父节点),那么改node和action将一直不会被释放。


原因:

在node调用runAction时,会将动画交给ActionManager来管理,即调用ActionManager::addAction,看该函数的实现:

void ActionManager::addAction(Action *action,Node *target,bool paused)
{
    //...
    if (! element)
    {
        element = (tHashElement*)calloc(sizeof(*element),1);
        element->paused = paused;
        target->retain();   //!!!watch out!!!
        element->target = target;
        HASH_ADD_PTR(_targets,target,element);
    }
    //...

注意这里会把node给retain一次,那它是在哪里release的呢,看下面:

void ActionManager::update(float dt)
{
    //...
    elt = (tHashElement*)(elt->hh.next);
    if (_currentTargetSalvaged && _currentTarget->actions->num == 0)
    {
        deleteHashElement(_currentTarget);
    }
    //...
}
void ActionManager::deleteHashElement(tHashElement *element)
{
    ccArrayFree(element->actions);
    HASH_DEL(_targets,element);
    element->target->release();   // release node
    free(element);
}

也就是说,当一个node在运行一个action时会被retain(referenceCount+1),在action运行完成后就会被release(referenceCount-1)。这么看起来没什么问题,但是当这个node不在running状态时,即没有添加到任何节点,通过create创建下一帧应该被自动释放,如果这时候给它运行了一个动画(ActionManager::addAction时第三个参数paused为true),再看update函数:

void ActionManager::update(float dt)
{
    if (! _currentTarget->paused)  //动画不会被执行
    {
        //...
    }
    //...
    elt = (tHashElement*)(elt->hh.next);
    if (_currentTargetSalvaged && _currentTarget->actions->num == 0)
    {
        deleteHashElement(_currentTarget);
    }
    //...
}

此时动画一直不会执行,也就是说动画不会完成,那么actions->num不可能等于0,则该节点就一直不会被释放。


解决方法:

void ActionManager::update(float dt)
{
    //...
    elt = (tHashElement*)(elt->hh.next);
    if (_currentTargetSalvaged && _currentTarget->actions->num == 0)
    {
        deleteHashElement(_currentTarget);
    }
    //if some node refrence 'target',it's refrence count >= 2 (issues #14050) else if (_currentTarget->target->getReferenceCount() == 1) { deleteHashElement(_currentTarget); } //... }

那么问题来了:为什么会有这样的行为呢——创建一个node,不加到任何节点,还给它run一个action?
这里解释过一遍了:https://github.com/cocos2d/cocos2d-x/pull/14090

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读