简体   繁体   中英

What's causing this memory leak?

The Problem

I'm currently building an iPad game using SpriteKit . The gameplay is driven by sound provided by EZAudio . After running the Instrumentation tools to profile my app, I noticed that whenever the GameViewController is shown memory allocation jumps up. When I repeatedly show the screen (5+ times) it crashes the app. My project uses ARC .

Navigation

The navigation consists of 4 ViewControllers :

  1. MenuViewController : This shows the menu
  2. CharacterSelectionViewController : It lets you a pick a character to use
  3. GameViewController : This lets you play a game with the player chosen
  4. ScoreViewController : It shows you the score you achieved in the game

1 - MenuViewController

From here you can navigate to CharacterSelectionViewController via a Show (eg Push ) segue.

2 - CharacterSelectionViewController

You can navigate to GameViewController via a Show (eg Push) segue. There is also a back button that goes back to MenuViewController with the following code:

[self.navigationController popViewControllerAnimated:YES];

3 - GameViewController

  1. It first shows a 5 second countdown (using NSTimer )
  2. The game starts with the character chosen in CharacterSelectionViewController
  3. The game can be paused, allowing you to quit and go back to MenuViewController via a manual Show Detail (eg Replace) segue.
  4. When the game ends, a manual Show (eg Push) segue is called that navigates to the ScoreViewController .

It's view hierarchy consists of three sets of view - one for the countdown, one for the pause menu and one for the game. These are subsequently shown/hidden. See the view hierarchy below:

GameViewController视图层次结构

4 - ScoreViewController

This allows you to quit or restart the game. When quit it pressed it performs a Show Detail (eg Replace) segue to MenuViewController . If restart is pressed it performs an unwind to CharacterSelectionViewController .

Responses

Please provide answers regarding:

  • How this kind of leak could occur
  • Any observations you have from the allocation and leaks screenshots

Allocation

Below, you can see the increasing allocations as I cycle through the apps screens to repeatedly show the GameViewController . I used Mark Generation to be able to show the increase in memory allocations.

分配

Leaks

Here you can see the memory leak that occurred. This is ordered by size.

泄漏

Ignore the leaks for the moment; fix the generational accretion first.

Is that generation snapshot representative of what is left after a typical snapshot? Typically, you'd want to show view controller, take snapshot, hide then show view controller, take snapshot, etc... as many times as you can without crashing (or 10 times if it doesn't crash).

Then look at generation 3 or 4 as that'll be the most stable representation of per-generation accretion.

If it is representative, it looks like you are leaking everything that the view controller would normally allocate. Ultimately, you are looking for the "root" of your object graph that is keeping everything around. Fix the reason why the root is sticking around and the rest'll likely go away.

I wrote a weblog post about this. It is a bit outdated, but the analysis workflow remains the same.

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

How are you unwinding from your various view controllers? I note that you mention that when the game ends you're pushing another VC onto the stack, but I presume this VC chain will at some point unwind back to your initial menu? (In essence, I wonder if you're just looping around, hence adding new VCs to the stack everytime you play a game.)

To create an un-wind segue, simply create an empty method in the destination VC (ie: your main menu) as such:

- (IBAction)unwindToMainMenu:(UIStoryboardSegue*)sender
{
    // Intentional NOP
}

(NB: Make sure it's also listed in the header.)

You can then call this as you would any other segue in your storyboard by dragging from the source object in question to the exit option at the top of the VC that contains the source object in the storyboard. This will present you with a list of segues to choose from. (You can verify that the segue is setup correctly by selecting the source object in the storyboard - the Connections inspector should list the unwind segue within the Triggered Segues section.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM