2

我正在使用 Cocos2D for iOS 开发游戏。

有一些像菜单之类的场景和一个主要的游戏场景。在主场景中只有三个动态对象。这些对象周期性地互相射击(直到这些对象被杀死或移出场景)。

现在的问题是:游戏不断消耗内存。我想找出我做错了什么。

没有像过度保留的物体这样的明显泄漏。场景被dealloc编辑,对象被从父母身上移除并被清理,动画被停止等等。

无论如何,记忆一直在某个地方。我正在使用以下代码

+ (void) reportMemory
{
    struct task_basic_info info;
    mach_msg_type_number_t size = sizeof(info);
    kern_return_t kerr = task_info(mach_task_self(),
                                   TASK_BASIC_INFO,
                                   (task_info_t)&info,
                                   &size);
    if (kerr == KERN_SUCCESS)
        NSLog(@"Memory in use (in Kbytes): %f", info.resident_size / 1024.0);
    else
        NSLog(@"Error with task_info(): %s", mach_error_string(kerr));
}

找出每个场景开始时消耗了多少内存。并且报告的数字总是大于前一个。

我尝试使用分配分析器,但老实说,我无法找出任何有用的东西。我看到总生存字节基本相同,但进程不断分配和释放一些东西。

你建议我看什么?基本上,我正在寻求有关如何在我的情况下调试内存操作的建议。

编辑(对我有什么帮助):

原来我打开了 NSZombieEnabled。基本上,这是内存消耗不断增加的主要因素。可以在@coneybeare 答案中找到一些有用的信息和提示

第二个最有用的事情是按照@Jack 的建议使用 Instruments (Leaks and Allocations)。它帮助我找到了几个微妙的漏洞。

4

3 回答 3

5

Instruments绝对是你的朋友,是什么东西会吃掉内存然后你就能看到它。

您应该使用的第一件事是泄漏工具(不是分配工具),它将通过每 X 秒采样一次内存来显示泄漏。

如果您单击特定的已识别泄漏,您可以看到

  • 在发现泄漏负责调用链中
  • 通过单击B中的小箭头,您可以看到内存泄漏的确切生活进程(例如当它被 malloc'd、retained、release 等时)

泄露 Xcode

如果这还不够,通过选择分配工具,您在左侧有一个标记为Mark Heap的按钮。每次单击此按钮都会创建堆的快照,并且它能够向您显示确切的差异,以便您能够查看在不应该有的两个时刻之间是否有分配的内存和从未释放的内存.

在此处输入图像描述

有了这些,我总能找到任何与内存相关的问题!

于 2012-06-04T14:02:47.820 回答
3

我将首先查看纹理缓存,如下所示:

[[CCTextureCache sharedTextureCache] dumpCachedTextureInfo];

在每个场景开始时这样做。纹理可以是真正的内存猪。可能您以某种方式保留了一些纹理(一种快速的方法是通过也在某处缓存中的 spriteFrames),或者保留的引用可能在您的数据模型中的某个地方。这是我的#if DEBUG memoryWarning 委托:

- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
    CCLOG(@"AppDelegate<applicationDidReceiveMemoryWarning> : before purging all caches");
    [[CCTextureCache sharedTextureCache] dumpCachedTextureInfo];
    [[CCSpriteFrameCache sharedSpriteFrameCache] removeUnusedSpriteFrames];
    [[CCDirector sharedDirector] purgeCachedData];
    CCLOG(@"AppDelegate<applicationDidReceiveMemoryWarning> : after purging all caches");
    [[CCTextureCache sharedTextureCache] dumpCachedTextureInfo];
}
于 2012-06-04T14:37:35.587 回答
2

确保你没有在 Cocos 层次结构中保留任何对象;Cocos 内置的清理对象的方法并不总是有效,除非 Cocos 拥有它们的唯一控制权和所有权;如果您将 Sprite 或 Layers 存储为保留的 iVar,将它们的引用计数增加到超出正常 Cocos 所有权的范围,那么它们可能无法按预期清理。assign出于这个原因,我在保存指向 Cocos 对象的指针时总是使用属性。

于 2012-06-04T16:05:06.170 回答