昨天测试“角色被遮挡部分透明显示”功能时,发现角色死亡后,其轮廓精灵不会消失。调试发现,角色在死亡时,其引用计数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误用导致引用计数循环引用的更多相关文章

  1. 【iOS】自动引用计数 (循环引用)

    历史版本 ARC(Automatic Reference Counting,自动引用计数)极大地减少了Cocoa开发中的常见编程错误:retain跟release不匹配.ARC并不会消除对retain ...

  2. 从urllib2的内存泄露看python的GC python引用计数 对象的引用数 循环引用

    这里会发现上述代码是存在内存泄露,造成的原因就是lz与ow这两个变量存在循环引用,Python 不知道按照什么样的安全次序来调用对象的 __del__() 函数,导致对象始终存活在 gc.garbag ...

  3. nodejs中相互引用(循环引用)的模块分析

    话不多少,直接上源码吧: modA.js: module.exports.test = 'A'; const modB = require('./05_modB'); console.log( 'mo ...

  4. 【转】iOS学习之容易造成循环引用的三种场景

    ARC已经出来很久了,自动释放内存的确很方便,但是并非绝对安全绝对不会产生内存泄露.导致iOS对象无法按预期释放的一个无形杀手是——循环引用.循环引用可以简单理解为A引用了B,而B又引用了A,双方都同 ...

  5. Block循环引用问题研究

    自从苹果在objc中添加Block功能支持以后已经过了很久.目前网上对于Block的使用有很多介绍.不过对于Block的内存管理问题,则是众说纷纭.再加上objc开始使用ARC以后,对于Block的内 ...

  6. 【原】iOS容易造成循环引用的三种场景,就在你我身边!

    ARC已经出来很久了,自动释放内存的确很方便,但是并非绝对安全绝对不会产生内存泄露.导致iOS对象无法按预期释放的一个无形杀手是——循环引用.循环引用可以简单理解为A引用了B,而B又引用了A,双方都同 ...

  7. Swift2.1 语法指南——自动引用计数

    原档: https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programm ...

  8. iOS容易造成循环引用的三种场景

    iOS容易造成循环引用的三种场景  ARC已经出来很久了,自动释放内存的确很方便,但是并非绝对安全绝对不会产生内存泄露.导致iOS对象无法按预期释放的一个无形杀手是--循环引用.循环引用可以简单理解为 ...

  9. swift学习笔记之-自动引用计数

    //自动引用计数 import UIKit /*自动引用计数(Automatic Reference Counting) 防止循环强引用 Swift 使用自动引用计数(ARC)机制来跟踪和管理你的应用 ...

随机推荐

  1. [hackerrank]Palindrome Index

    简单题. #include <iostream> #include <string> using namespace std; int main() { int T; cin ...

  2. python 利用pop3接收邮件并保存附件

    def SaveAttach():# login the pop3 server ,retrive the new mails ,and download the attachments dstdir ...

  3. Spring IoC — 基于XML的配置

    1.属性注入 注意点: 1)如果类中显示定义了一个带参的构造函数,则一定还要显示提供一个无参构造函数,否则使用属性注入时将抛出异常. 2)JavaBean关于属性命名的特殊规范.Spring只会检查B ...

  4. mysql 插入汉字 异常 Incorrect string value: '\xE8\xA7\x84\xE5\x88\x99' for column 'name'

    今天使用mysql出现 Incorrect string value: '\xE8\xA7\x84\xE5\x88\x99' for column 'name' 异常 通过查找问题,发现是字段编码不支 ...

  5. redis sentinel 配置

    在最小配置:master.slave各一个节点的情况下,不管是master还是slave down掉一个,“完整的”读/写功能都将受影响,这在生产环境中显然不能接受.幸好redis提供了sentine ...

  6. Hadoop集群(第7期)_Eclipse开发环境设置

    1.Hadoop开发环境简介 1.1 Hadoop集群简介 Java版本:jdk-6u31-linux-i586.bin Linux系统:CentOS6.0 Hadoop版本:hadoop-1.0.0 ...

  7. ZOJ 3790 Consecutive Blocks (离散化 + 暴力)

    题目链接 虽然是一道暴力的题目,但是思路不好想.刚开始还超时,剪枝了以后1200ms,不知道为什么还是这么慢. 题意:给你n个点,每个点有一种颜色ci,给你至多k次删除操作,每次删除一个点,问最多k次 ...

  8. Android ArrayAdapter 详解

    本文主要讲解ArrayAdapter的创建方法,我把ArrayAdapter分为三种:简单的.样式丰富的但内容简单的.内容丰富的. 默认的,ArrayAdapter期望接受的样式文件里只含有一个tex ...

  9. Deferred的那些知识

    在移动开发中的各种中,我们一定会遇到异步回调的问题,比如: 1:Css3执行动画完毕, 回调 2:Jquery Animate动画的执行完毕, 回调 3:Ajax的执行(并行.串行),回调 等等   ...

  10. BZOJ 2179 FFT快速傅里叶

    fft. #include<set> #include<map> #include<ctime> #include<queue> #include< ...