3.1.1另一个可能的内存泄露

开发中,为了检测内存泄露,在加载一个scene时,对一个ui的ExportJson循环做了100次loading

for (int i = 0 ; i < 100 ; ++i)
{
alayout = static_cast<Layout*>(cocostudio::GUIReader::getInstance()->widgetFromJsonFile(filePath));
}

理论上,pop掉这个scene时,内存消耗应该回复到加载之前的水平,但实际发现内存峰值上升了100多M,这是肯定不正常的,
经过检查,发现是由于Button控件初始化时创建了多个Sprite和Label

void Button::initRenderer()
{
_buttonNormalRenderer = Sprite::create();
_buttonClickedRenderer = Sprite::create();
_buttonDisableRenderer = Sprite::create();
_titleRenderer = Label::create();
_titleRenderer->setAnchorPoint(Vec2::ANCHOR_MIDDLE);

addProtectedChild(_buttonNormalRenderer, NORMAL_RENDERER_Z, -1);
addProtectedChild(_buttonClickedRenderer, PRESSED_RENDERER_Z, -1);
addProtectedChild(_buttonDisableRenderer, DISABLED_RENDERER_Z, -1);
addProtectedChild(_titleRenderer, TITLE_RENDERER_Z, -1);

}

但在Button析构的时候,这几个组件并没有被释放
通过查看这些组件的引用值,发现_protectedChildren析构的时候,引用值都大于2,导致在_protectedChildren析构时,这些子组件都得不到释放
具体原因可能是因为这些组件上可能调用了runAction
而且,经过长时间之后,内存峰值始终没有下降,并且,每次加载这个scene后,内存都会成倍增长,判定必定是内存泄露无疑。猜测可能是因为前99次loading获得的layout不会调用onEnter, 这些action处于pause状态,无法结束,最终导致这些组件也无法释放。

对于这个问题,我直接修改了ProtectedNode的析构函数,析构时做了一次removeAllProtectedChildrenWithCleanup(true),问题解决

ProtectedNode::~ProtectedNode()
{
CCLOGINFO( “deallocing ProtectedNode: %p - tag: %i”, this, _tag );
removeAllProtectedChildrenWithCleanup(true);

}

另外,我发现Node的析构里也没有removeAllProtectedChildrenWithCleanup,理论上Node也会有这样的问题,所以Node的析构里我也加上了这个调用。

内存泄露对开发是一个大忌,希望cocos2dx团队能在这个方面加大一些检查力度:)

这么好的帖子必须顶!

【另外,我发现Node的析构里也没有removeAllProtectedChildrenWithCleanup,理论上Node也会有这样的问题,所以Node的析构里我也加上了这个调用。】

cocos2d-x 的Node里面没有removeAllProtectedChildrenWithCleanup这个方法啊?

没有官方的人啊。。。。。。。。。。。。。。。。。。。