Memory will not be released in iOS app using ARC

I created a simple petty game using ARC. While profiling memory usage with the Allocations profiling tool in Xcode, I see that memory is not always freed. For one example of a problem, I have a class for an ActivePlayer object:

ActivePlayer.h:

@interface ActivePlayer : NSObject

@property (nonatomic, strong) NSString * name;
@property (nonatomic) NSInteger overallScore;
@property (nonatomic) NSInteger questionScore;

- (id) initWithName:(NSString *)name;

@end

      

ActivePlayer.m:

#import "ActivePlayer.h"

@interface ActivePlayer ()

@end


@implementation ActivePlayer

- (id) initWithName:(NSString *)name
{
    self = [self init];
    if (self) {
        self.name = name;
        self.overallScore = 0;
    }
    return self;
}

/*
- (void)dealloc
{
    self.name = nil;
}
*/
@end

      

And the ActivePlayer is created in the createPlayer method in the ActiveGame class:

[[ActivePlayer alloc] initWithName:name]

      

I am doing the following test case: I start a new game (which highlights one ActivePlayer), I answer one question, and then the game ends (and at this point the ActivePlayer is released). Then I can start a new game and repeat this cycle (each cycle is a "game" as described below). When using the Allocations profiling tool, I expect to see that memory was allocated in the middle of the game, but freed after the game was over (no matter how many times I play the game). But I found that this is not always the case:

BTW: each bulleted line below describes a line in the Object List tab of the Allocations tool; this site will not allow me to post a screenshot, hence a text description. All lines are Live; I only view created and universes.

While game # 1 is running, I see the following distributions.

  • Category = ActivePlayer; Size = 16; Responsible Caller = - [ActiveGame createPlayer:]
  • Category = Malloc 48 bytes; Size = 48; Responsible Caller = - [ActivePlayer initWithName:]

After completing game # 1, I see the following. The ActivePlayer has been released, but 48 bytes are still Live.

  • Category = Malloc 48 bytes; Size = 48; Responsible Caller = - [ActivePlayer initWithName:]

If I start game # 2, I see the following while playing. In addition to the game from game # 1, there are two new distributions.

  • Category = Malloc 48 bytes; Size = 48; Responsible Caller = - [ActivePlayer initWithName:]
  • Category = ActivePlayer; Size = 16; Responsible Caller = - [ActiveGame createPlayer:]
  • Category = Malloc 144 bytes; Size = 144; Responsible Caller = - [ActivePlayer initWithName:]

And after finishing game # 2, I see the following. Again, the ActivePlayer has been freed, but the "Malloc X Bytes" allocations still exist.

  • Category = Malloc 48 bytes; Size = 48; Responsible Caller = - [ActivePlayer initWithName:]
  • Category = Malloc 144 bytes; Size = 144; Responsible Caller = - [ActivePlayer initWithName:]

After that I get unusual results - if I play games # 3, # 4 and # 5, I never see the in-game lines for Category = "Malloc X Bytes", only for the Category = ActivePlayer line, which is released after the game ends. The first two lines of "Malloc", as shown above, continue to persist. I also saw another weird behavior - when testing this yesterday using the iPhone 6.0 simulator, only games # 2 and # 3 remained alive, but not games # 1, # 4 and # 5. So, as long as the memory remains allocated, the times at which it occurs appear to be different on my device and in different versions of the simulator.

And my questions are:

  • As far as I understood, after finishing the game, I shouldn't see live memory from the initWithPlayer call and the ActivePlayer object was freed?
  • If so, what is causing it and how to free it?
  • Or don't I need to worry about it at all?

Notes:

  • These screenshots are taken from running my app on an iPhone 4 running iOS 6.1. But I see similar behavior works with iPhone Simulator for 5.1, 6.0 and 6.1 and I saw it on my iPhone running iOS 6.0 before I updated it.
  • In ActivePlayer.m, the dealloc method is currently commented out, although I tested it while it was uncommented and verified that it was called (by the system, I don't call the dealloc call anywhere). Either way, the behavior is the same.
  • For what's worth, nothing is communicated with the Leaks profiling tool.
  • While this is one example that results in 192 bytes of live memory which I believe should be freed up, I see this with many of my classes, i.e. it seems that the memory allocation grows over time, which I think is is the problem.
+3


source to share


3 answers


Your code is ok. It looks like you are still maintaining a link to the original ActivePlayer, somewhere else in your code.

As a side note, your template for creating an ActivePlayer is not the norm - usually the class does not call alloc from the init method. Instead, the caller should do:

[[ActivePlayer alloc] initWithName:@"Bob"];

      



and your init method should work with the return value

[super init];

      

+3


source


I find it very strange that your constructor is static (+ sign). The naming convention specifies that methods with names prefixed with as init

return managed memory objects. I suspect that the results of the inner method are evaluated by their method names.



+2


source


I think checking the instance count has determined that your code is not leaking ActivePlayers. As an aside, the best form for constructor and inits looks like this:

// .h

@interface ActivePlayer : NSObject

+ (id)activePlayerWithName:(NSString *)name;

@end

// .m

+ (id)activePlayerWithName:(NSString *)name {
    return [[self alloc] initWithName:name];
}

// if you want to make this public (include in .h interface) you can
// the callers will have the choice of alloc init pattern, or the factory
//
- (id)initWithName:(NSString *)name {
    self = [self init];
    if (self) {
        _name = name;
    }
    return self;
}

      

Then the caller does the following:

ActivePlayer *activePlayer = [ActivePlayer activePlayerWithName:@"Charlie"];

      

+1


source







All Articles