IOS allocated objects is not referenced later in this execution path retain count +1
Asked Answered
P

4

7

In my appDelegate.h file I do this:

CLLocationManager       *locationManager;

and

@property (nonatomic, retain) CLLocationManager *locationManager;

Then later in the .m file:

...

@synthesize locationManager;
...
if ([CLLocationManager locationServicesEnabled])
{

    [myGizmoClass setLocationManagerDisabled:FALSE];

    self.locationManager = [[CLLocationManager alloc] init];

    self.locationManager.delegate = self;

    [self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];

    [self.locationManager setDistanceFilter:kCLDistanceFilterNone];


    [self.locationManager startUpdatingLocation];

...

Yet I am getting the following in XCode 4.5 (see image attached)

Object leaked: allocated object is not referenced later in this code execution path

(Object leaked: allocated object is not referenced later in this code execution path)

What the heck? I reference it right after that line.

I am not seeing the issue. PS: No crash, or anything. Let me be clear. This is working as it is. I just hate the error. I am QUITE sure that I am missing something silly. Can anyone help?

Please do not post anything with regards to "You don't have to do @property anymore", etc. This code was written back for xcode 3.5-4~ish and I prefer being specific because I hate having to flip back and forth between the shorthand that XCode 4.5 allows and what older projects require (and still have in their source code). So I still use the full definitions in the .h file. I figured that the major change to programming style would come with the next major update of the app. (thanks for understanding)

Plovdiv answered 8/11, 2012 at 17:49 Comment(0)
S
12

Problem

If this is non ARC (which I assume it is), then think about how this is working:

self.locationManager = [[CLLocationManager alloc] init];
    ^                                        ^
    Retains on setting                       |
                                             Retains when allocating

Why is this retaining when I'm setting the property?

@property (nonatomic, retain) CLLocationManager *locationManager;
                         ^
                    This is why

When you synthesize a property, you are generating a getter and setter (in most circumstances). The nonatomic and retain keywords are providing hints to the synthesize; nonatomic wraps the setting and getting within @synchronized(self) to make sure only one thread is acting on it at a time, and retain is telling the setter to retain whatever value you're putting in to it. It's important to note (for older versions of Xcode anyway, not 4.5), that if you don't synthesize, then these won't take effect


In your case, you are retaining something twice. Hence if there's no release anywhere, then the memory will be leaked. It's simple to fix, simply use:

self.locationManager = [[[CLLocationManager alloc] init] autorelease];

Why does it act like this?

If it didn't, then autoreleased objects returned from methods wouldn't be retained correctly!

Alternative Solution

If you don't like adding autorelease, simply assign to the underlying instance variable instead.

locationManager = [[CLLocationManager alloc] init];

In all cases...

Make sure you release what you have at the most appropriate time, these will not automatically release. For retained properties, self.locationManager = nil will suffice. For the alternative solution, you will need to perform [locationManager release];

Sailmaker answered 8/11, 2012 at 17:54 Comment(0)
S
2

The @property is defined to retain. Therefore the following line:

self.locationManager = ...

Which is semantically equivalent to:

[self setLocationManager:...]

retains whatever is on the right hand side. But what you've supplied on the right hand side is an owning reference. So:

[[CLLocationManager alloc] init] // gives an owning reference

self.locationManager = ...       // retains your owning reference; you've now
                                 // incremented the reference count twice

Your location manager will be leaked.

Shelah answered 8/11, 2012 at 17:54 Comment(3)
The solution, if you're not using ARC, is to autorelease the location manager immediately after you create it.Quarterdeck
So, is self.locationManager = [[[CLLocationManager alloc] init] autorelease]; the answer? or should I have done: locationManager = [[CLLocationManager alloc] init]; when i created it instead (removing 'self.')?Plovdiv
@Plovdiv either would do it, it's a style question. As a general rule you shouldn't use getters or setters in your init or dealloc (because that's calling methods on a class that's only partially built or partly destroyed), otherwise it's as you prefer.Shelah
S
1

Check with this code:

CLLocationManager *location = [[CLLocationManager alloc] init];

self.locationManager = location;

[location release];

or you need to do like:

self.locationManager = [[[CLLocationManager alloc] init] autorelease];

[[CLLocationManager alloc] init] makes retainCount to 1.

self.locationManager makes the retainCount to increment by 1.

Stokehole answered 8/11, 2012 at 17:54 Comment(0)
O
1

In the @property, I see that you've indicated that you want locationManager to retain. So assigning something to self.locationManager will bump the retain count to one. However, since you also call alloc, that bumps the retain count to two now (which will cause a leak).

Solution: Remove self from the alloc statement:

locationManager = [[CLLocationManager alloc] init];

Oneman answered 8/11, 2012 at 17:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.