是啥导致了这种内存泄漏?

Posted

技术标签:

【中文标题】是啥导致了这种内存泄漏?【英文标题】:What's causing this memory leak?是什么导致了这种内存泄漏? 【发布时间】:2015-04-23 22:25:58 【问题描述】:

问题

我目前正在使用SpriteKit 构建一个 iPad 游戏。游戏由EZAudio 提供的声音驱动。在运行 Instrumentation 工具来分析我的应用程序后,我注意到 每当显示 GameViewController 时,内存分配就会上升。当我重复显示屏幕(5 次以上)时,它会使应用程序崩溃。我的项目使用ARC。

导航

导航由4个ViewControllers组成:

    MenuViewController:显示菜单 CharacterSelectionViewController:它可以让您选择要使用的角色 GameViewController:这让您可以与所选玩家一起玩游戏 ScoreViewController:显示您在游戏中取得的分数

1 - 菜单视图控制器

您可以从这里通过Show (e.g. Push) 转场导航到CharacterSelectionViewController

2 - CharacterSelectionViewController

您可以通过Show (e.g. Push) segue 导航到GameViewController。还有一个返回按钮可以返回MenuViewController,代码如下:

[self.navigationController popViewControllerAnimated:YES];

3 - 游戏视图控制器

    它首先显示 5 秒倒计时(使用 NSTimer) 游戏从CharacterSelectionViewController中选择的角色开始 游戏可以暂停,您可以通过手动Show Detail (e.g. Replace) segue 退出并返回MenuViewController。 当游戏结束时,会调用手动Show (e.g. Push) segue 导航到ScoreViewController

它的视图层次结构由三组视图组成——一组用于倒计时,一组用于暂停菜单,一组用于游戏。这些随后被显示/隐藏。请参阅下面的视图层次结构:

4 - ScoreViewController

这允许您退出或重新开始游戏。退出时,按下它会执行Show Detail (e.g. Replace) segue 到MenuViewController。如果按下重新启动,它将执行 unwindCharacterSelectionViewController

回复

请提供以下方面的答案:

这种泄漏是如何发生的 您对分配和泄漏屏幕截图的任何观察

分配

在下面,当我循环浏览应用程序屏幕以重复显示 GameViewController 时,您可以看到分配的增加。我使用Mark Generation 来显示内存分配的增加。

泄漏

在这里您可以看到发生的内存泄漏。这是按大小排序的。

【问题讨论】:

你怎么来和去这个控制器?您要使用 segue 回到以前的控制器吗? 嗨@rdelmar,是的,我通过Show (e.g. Push) segue 来到这个控制器。然后,我以两种方式之一离开 segue。第一个是通过Show Detail (e.g. Replace) segue 回到MenuViewController(层次结构中的两个视图,因此是前一个控制器)。第二个是Show (e.g. Push) segue 到另一个不是前一个控制器的控制器。 请查看我更新的问题以获得更详细的解释 【参考方案1】:

暂时忽略泄漏;先修复世代积累。

那一代快照是否代表了典型快照之后剩下的内容?通常,您希望显示视图控制器、拍摄快照、隐藏然后显示视图控制器、拍摄快照等...尽可能多地不崩溃(如果不崩溃,则为 10 次)。

然后看看第 3 代或第 4 代,因为这将是每代增长的最稳定表示。

如果它具有代表性,则看起来您正在泄漏视图控制器通常会分配的所有内容。最终,您正在寻找保持一切的对象图的“根”。修复根存在的原因,其余的可能会消失。

我为此写了一篇博客文章。它有点过时了,但分析工作流程保持不变。

http://www.friday.com/bbum/2010/10/17/when-is-a-leak-not-a-leak-using-heapshot-analysis-to-find-undesirable-memory-growth/

【讨论】:

【参考方案2】:

您是如何从各种视图控制器中解脱出来的?我注意到你提到当游戏结束时你正在将另一个 VC 推入堆栈,但我认为这个 VC 链会在某个时候展开回到你的初始菜单? (本质上,我想知道您是否只是在循环播放,因此每次玩游戏时都会向堆栈添加新的 VC。)

要创建一个 unwind segue,只需在 destination VC(即:您的主菜单)中创建一个空方法,如下所示:

- (IBAction)unwindToMainMenu:(UIStoryboardSegue*)sender

    // Intentional NOP

(注意:确保它也列在标题中。)

然后,您可以像在情节提要中的任何其他 segue 一样调用它,方法是从有问题的源对象拖动到情节提要中包含源对象的 VC 顶部的退出选项 .这将为您提供可供选择的 segue 列表。 (您可以通过在情节提要中选择源对象来验证转场设置是否正确 - 连接检查器应在 Triggered Segues 部分中列出展开转场。)

【讨论】:

以上是关于是啥导致了这种内存泄漏?的主要内容,如果未能解决你的问题,请参考以下文章

内存溢出和内存泄漏分别是啥意思?

内存泄漏和内存溢出的区别是啥

内存泄漏与溢出

这种对共享指针向量的回退是不是会导致内存泄漏?

托管 (.net) 应用程序中内存泄漏的最常见(并且经常被忽视)的原因是啥?

UITabBarItem 内存泄漏