CCCallFuncN误用导致引用计数循环引用
昨天测试“角色被遮挡部分透明显示”功能时,发现角色死亡后,其轮廓精灵不会消失。调试发现,角色在死亡时,其引用计数retain_count居然是9。这是由引用计数混乱引起的内存泄露。
加了很多日志跟踪retain_count,又通过调试,终于确定了问题,是我错误使用CCCallFuncN这个CCAction导致的。于是查看cocos2d-x2.2.1源代码了解这个类的实现原理。
CCCallFuncN是CCAction的子类,是函数回调动作。我在游戏中用这个类来实现“角色死亡后倒地4秒渐渐消失再删除精灵”功能。
PathFinder::_deadAction = CCSequence::createWithTwoActions(
CCFadeOut::create(4.0f),
CCCallFuncN::create(this, callfuncN_selector(PathFinder::callbackDead)));
其中,CCCallFuncN::create的第一个参数this将作为方法PathFinder::callbackDead的参数,CCCallFuncN内部会对其retain一次。
所以,PathFinder的成员引用了PathFinder,其retain_count至少是1,因此永远不会析构,循环引用导致内存泄露。
刚发现这个错误,我愚蠢地在_deadAction创建后面加了一个this->release(),这样日志中retain_count正常了,可是忘了当PathFinder析构时析构_deadAction又会对PathFinder做release()操作,导致retain_count变为负数断言。
改成这样即可,注意runAction时也会retain调用对象,目前还没发现问题:
_deadAction = CCSequence::createWithTwoActions(
CCFadeOut::create(4.0f),
CCRemoveSelf::create());
对于必须要使用CCFunc的函数,建议把该函数放到其他类中。
经验:
1.千万不能让对象持有引用了该对象的成员,特别是精灵create这种隐蔽的情况;
2.精灵create时,可能会retain传入的其他对象,当然我一般不会retain,因为有自己的内存管理规则。
3.析构函数加日志,确保确实析构。
CCCallFuncN误用导致引用计数循环引用的更多相关文章
- 【iOS】自动引用计数 (循环引用)
历史版本 ARC(Automatic Reference Counting,自动引用计数)极大地减少了Cocoa开发中的常见编程错误:retain跟release不匹配.ARC并不会消除对retain ...
- 从urllib2的内存泄露看python的GC python引用计数 对象的引用数 循环引用
这里会发现上述代码是存在内存泄露,造成的原因就是lz与ow这两个变量存在循环引用,Python 不知道按照什么样的安全次序来调用对象的 __del__() 函数,导致对象始终存活在 gc.garbag ...
- nodejs中相互引用(循环引用)的模块分析
话不多少,直接上源码吧: modA.js: module.exports.test = 'A'; const modB = require('./05_modB'); console.log( 'mo ...
- 【转】iOS学习之容易造成循环引用的三种场景
ARC已经出来很久了,自动释放内存的确很方便,但是并非绝对安全绝对不会产生内存泄露.导致iOS对象无法按预期释放的一个无形杀手是——循环引用.循环引用可以简单理解为A引用了B,而B又引用了A,双方都同 ...
- Block循环引用问题研究
自从苹果在objc中添加Block功能支持以后已经过了很久.目前网上对于Block的使用有很多介绍.不过对于Block的内存管理问题,则是众说纷纭.再加上objc开始使用ARC以后,对于Block的内 ...
- 【原】iOS容易造成循环引用的三种场景,就在你我身边!
ARC已经出来很久了,自动释放内存的确很方便,但是并非绝对安全绝对不会产生内存泄露.导致iOS对象无法按预期释放的一个无形杀手是——循环引用.循环引用可以简单理解为A引用了B,而B又引用了A,双方都同 ...
- Swift2.1 语法指南——自动引用计数
原档: https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programm ...
- iOS容易造成循环引用的三种场景
iOS容易造成循环引用的三种场景 ARC已经出来很久了,自动释放内存的确很方便,但是并非绝对安全绝对不会产生内存泄露.导致iOS对象无法按预期释放的一个无形杀手是--循环引用.循环引用可以简单理解为 ...
- swift学习笔记之-自动引用计数
//自动引用计数 import UIKit /*自动引用计数(Automatic Reference Counting) 防止循环强引用 Swift 使用自动引用计数(ARC)机制来跟踪和管理你的应用 ...
随机推荐
- lintcode:Palindrome Partitioning 分割回文串
题目: 分割回文串 给定一个字符串s,将s分割成一些子串,使每个子串都是回文串. 返回s所有可能的回文串分割方案. 样例 给出 s = "aab",返回 [ ["aa&q ...
- 缓存初解(五)---SpringMVC基于注解的缓存配置--web应用实例
之前为大家介绍了如何使用spring注解来进行缓存配置 (EHCache 和 OSCache)的简单的例子,详见 Spring基于注解的缓存配置--EHCache AND OSCache 现在介绍一下 ...
- 高效的Nginx
FastCGI是将CGI解释器进程保持在内存中并因此获得较高的性能.CGI解释器的反复加载是CGI性能低下的主要原因. 如果CGI解释器保持在内存中并接受FastCGI管理器的调度,则可以提供良好的性 ...
- jQuery编程基础精华01(jQuery简介,顶级对象$,jQuery对象、Dom对象,链式编程,选择器)
jQuery简介 什么是jQuery? jQuery就是一个JavaScript函数库,没什么特别的.(开源)联想SQLHelper类 jQuery能做什么?jQuery是做什么的? jQuery本身 ...
- 虚函数(virtual)为啥不能是static
静态成员函数,可以不通过对象来调用,即没有隐藏的this指针. virtual函数一定要通过对象来调用,即有隐藏的this指针. static成员没有this指针是关键!static function ...
- Java API —— 递归
1.方法定义中调用方法本身的现象 2.递归注意实现 1) 要有出口,否则就是死递归 2) 次数不能太多,否则就内存溢出 3) 构造方法不能递归使用 3. ...
- PHP之APC缓存详细介绍(转)
1.APC缓存简介 APC,全称是Alternative PHP Cache,官方翻译叫”可选PHP缓存”.它为我们提供了缓存和优化PHP的中间代码的框架. APC的缓存分两部分:系统缓存和用户数据缓 ...
- TCP protocol
he characteristics of TCP protocol TCP (which means Transmission Control Protocol) is one of the mai ...
- Dozer应用——类之间值的映射
1. Mappings via Annotation public class SourceBean { private Long id; private String name; @Mapping( ...
- Oracle数据库ORA-12154: TNS: 无法解析指定的连接标识符详解
ORA-12154: TNS: 无法解析指定的连接标识符(转自http://www.cnblogs.com/psforever/p/3929064.html) 相信使用过Oracle数据库的人一定碰到 ...