可能造成“Received Memery Warning”的一种原因

来源:互联网 发布:linux 移动文件命令 编辑:程序博客网 时间:2024/05/21 22:57

我的游戏使用到了cocos2d 框架,游戏结构比较简单,一个 MenuScene, 一个 GameScene

GameScene继承自 CCLayer

由于要使用一个比较大的地形(总之比iTouch4g的屏幕要大)

因此我选择使用可以移动的场景用来实现这个功能

之前我的GameScene就是仅有的一个 CCLayer 对象~

但是如果要实现场景的移动的话,则必须要在这个CCLayer里面在添加一个 子  CCLayer 对象

将位置不用改变的小地图,joyStick,游戏暂停重来等按钮放在母层里面,

这样游戏场景在被移动的时候,这些位置不用改变的元素就不会随着游戏场景腾挪

然而,就在这个时候,问题出现了~

这个问题我也是偶然才发现的,之前游戏的持久性我都有过测试,“重来”一百次也不会有什么问题

说明在GameScene dealloc的时候将该干掉的都给干掉了,

但是在我增加子层了之后,我发现对于比较复杂的地图,重来不了两下游戏就会crash掉

查看控制台,发现爆出的错误就是 “Received Memery Warning”

除此之外,再没有其他的提示~

于是我求助Google大神,但是收效甚微

我一遍又一遍的重来,试图能够发现导致游戏崩溃的根本原因

在xcode4。2里面,我发现已经找不到Instruments的身影了

这也是在可以理解的范围,毕竟XCode从3个多G降到1个多G,不能不说被阉割掉了很多东西

我发现了一个比较有意思的功能,Analyze,快捷键是 Command + shift + b

Command +b是生成的快捷键,这是一个很常用的快捷键,对我来说仅次于 Command +r(编译并且在完成之后运行)了~

这个Analyze相当于对源代码进行处理,将有可能导致内存泄露的地方给报告出来~

不能说这个功能很鸡肋,因为我确实靠这个功能找到了几处没有delete的对内存分配

但是,也是仅此而已,我并没有靠着这个功能找到 Received Memery Warnning的原因~

如果用Cocos2d用的比较多的肯定都知道,凡继承自CCNode的类型在一定程度上如果作为Scene场景的成员节点

都是不用在Scene的 dealloc方法中自主去释放掉的,cocos2d会“很智能”的将这些子节点给清理掉~

离我的问题很近了!!就是因为cocos2d有点儿智能但是又不是智能到完美无缺,因此才导致了我所遇到的问题!!

这个也是我整了一个下午灵光一闪间突然想到的,我就像,母层的dealloc虽然是能将其下的所有子节点给清理掉了

但是,子层里面如果也是以容器的身份出现,里面也盛放了很多孙子节点,那么祖母节点不一定能将这些孙子辈们给干掉~

事实证明我的猜测不错,我先后试过这么一些方法:

1。将子层由CCLayer改成CCNode;(不管用,重来不到10次依然会内存耗尽崩溃)

2。在母层的dealloc方法中主动去调用子层的dealloc方法(重来的第一次就会报错,很明显,子层将会被dealloc两次,肯定会造成类似内存访问出错的错误)

3。我在母层的dealloc方法中,在 【super dealloc】之前添加子层 removeAllChildrenWithCleanup:YES的代码

在第3种方法的实验过程中,我得到了满意的结果,即使重来100次,Received Memery Warning 的错误也不会再报出了~

那么,更加证明了我的推测:

Scene 的 dealloc 仅能智能地将所有的子辈节点给 dealloc 掉,

如果子辈中有充当容器身份的 CCLayer,是不能将其所包含的孙子辈继承自 CCNode 的对象智能清理掉的!!

用一句形象的话语来概括:山高皇帝远 ^ ^

PS:其实以前如果在Scene中添加其他类似容器这样的CCLayer的时候,都会新建一个类

在这个新建出来的类的dealloc方法中做好所有的清理工作

这样倒是不会有什么问题了,因为所谓的智能清理也不过就是调用所有子辈节点的dealloc方法

换句话说,如果子辈的dealloc方法没有给子辈自己擦好屁股以至于发生了内存泄露,母亲大人也是毫无办法的~