cocos2dx - ActionManager内存泄露
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
cocos2dx - ActionManager内存泄露的更多相关文章
- cocos2d-x 从onEnter、onExit、 引用计数 谈内存泄露问题
/////////////////////////////////// //author : zhxfl //date : 2013.8.29 //email : 291221622@qq.co ...
- quick cocos2dx lua 内存释放
前言 对于内存的优化,网上有很多例子和教程.总体来说,就那么几种解决方案,在最后我会简单提下,这里先说下在quick中,对于图片的处理. 1.查看内存调试信息 对于quick框架的了解,我们可以参考\ ...
- cocos2d-x之内存管理(4)
c++的内存管理一直以来都是个问题,也有多种实现方案,比如智能指针,使用引用计数等,cocos2d-x也需要涉及到内存的管理. cocos2d-x是如何管理内存的呢? cocos2d-x的内存管理主要 ...
- cocos2dx的内存管理机制
首先我们必须说一下c++中变量的内存空间的分配问题,我们在c++中写一个类,可以在栈上分配内存空间也可以使用new在堆上分配内存空间,如果类对象是在栈上分配的内存空间,这个内存空间的管理就不是我们的事 ...
- 引用计数的cocos2dx对象内存管理和直接new/delete box2d对象内存管理冲突的解决方法
转载请注明: http://blog.csdn.net/herm_lib/article/details/9316601 项目中用到了cocos2dx和box2d,cocos2dx的内存是基于引用计数 ...
- java: web应用中不经意的内存泄露
前面有一篇讲解如何在spring mvc web应用中一启动就执行某些逻辑,今天无意发现如果使用不当,很容易引起内存泄露,测试代码如下: 1.定义一个类App package com.cnblogs. ...
- 查看w3wp进程占用的内存及.NET内存泄露,死锁分析
一 基础知识 在分析之前,先上一张图: 从上面可以看到,这个w3wp进程占用了376M内存,启动了54个线程. 在使用windbg查看之前,看到的进程含有 *32 字样,意思是在64位机器上已32位方 ...
- C++11 shared_ptr 智能指针 的使用,避免内存泄露
多线程程序经常会遇到在某个线程A创建了一个对象,这个对象需要在线程B使用, 在没有shared_ptr时,因为线程A,B结束时间不确定,即在A或B线程先释放这个对象都有可能造成另一个线程崩溃, 所以为 ...
- 基于HTML5的WebGL应用内存泄露分析
上篇(http://www.hightopo.com/blog/194.html)我们通过定制了CPU和内存展示界面,体验了HT for Web通过定义矢量实现图形绘制与业务数据的代码解耦及绑定联动, ...
随机推荐
- iOS的KVO使用和轻量级封装
KVO的使用方法 注冊 [object addObserver:observer forKeyPath:@"text" options:NSKeyValueObservingOpt ...
- 利用python进行数据分析——(一)库的学习
总结一下自己对python常用包:Numpy,Pandas,Matplotlib,Scipy,Scikit-learn 一. Numpy: 标准安装的Python中用列表(list)保存一组值,可以用 ...
- java的foreach,后台弹框
for (String string : list) { if(string.equals(ids)){ int res = JOptionPane.showConfirmDialog(null, & ...
- [转]asp.net Request、Response 响应在此上下文中不可用
这个问题一般是在页面中使用了Respons.Write()方法,虽然是继承了System.Web.UI.Page.但System.Web.UI.Page下的Response只有在asp.net页面里才 ...
- HDU 1017A Mathematical Curiosity (暴力统计特殊要求个数)
传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1017 A Mathematical Curiosity Time Limit: 2000/1000 M ...
- Many-to-many relationships in EF Core 2.0 – Part 4: A more general abstraction
In the last few posts we saw how to hide use of the join entity from two entities with a many-to-man ...
- UCOS阅读问题累积
1.#ifdef __cplusplus extern "C" { #endif 作用: 一般用于将C++代码以标准C形式输出(即以C的形式被调用),这是因为C++虽然常被认 ...
- javascript入门教程 (1)
对于刚刚接触前端开发或者刚开始学习javascript的同学来说,js能用来做些什么,它是如何诞生的,它的组成结构是怎么的,在这些问题上可能都只有一些模糊的概念, js的入门篇 就是希望可以从0开始深 ...
- Swift_函数
Swift_函数 点击查看源码 定义和调用函数 //定义和调用函数 func testDefiningAndCallingFunctions() { func sayHello(_ personNam ...
- #leetcode刷题之路14-最长公共前缀
编写一个函数来查找字符串数组中的最长公共前缀. 如果不存在公共前缀,返回空字符串 "". 示例 1: 输入: ["flower","flow" ...