Potential leak of an object warning -- clarification needed - objective-c

After I Analyzed my code, Xcode indicated a potential leak as shown below.
Is this something I should be concerned about?
In this code, the class that sets doublyLinkedList is the sole owner and continues to manage this object throughout program execution.

The reason you're getting the warning is because the new call returns a retained object, and then your setter is probably doing another retain on it (depends on whether it's synthesized or manually generated).
Also, I would recommend you use the standard alloc/init instead of new, so that the two-phase creation is obvious.
This is better:
if (self) {
DoublyLinkedList *dll = [[[DoublyLinkedList alloc] init] autorelease];
self.doublyLinkedList = dll;
}
or just
if (self) {
self.doublyLinkedList = [[[DoublyLinkedList alloc] init] autorelease];
}

You may wish to do this instead:
if (self) {
DoublyLinkedList *dll = [DoublyLinkedList new];
self.doublyLinkedList = dll;
[dll release];
}
In the header, declare doublyLinkedList a #property that is retained.

You have a "potential leak" because the Analyzer sees that you have allocated memory for a DoublyLinkedList instance (using new), put it into a local variable called dll, and not released that memory in the same scope.
Assuming that the doublyLinkedList member that you're setting happens to also be a property declared as retaining, you also have an actual leak, because you have over-retained the DoublyLinkedList that you create here.
The ownership rules say that you have one claim on this instance because you called new to create it. When you pass the instance to setDoublyLinkedList:, it is retained, and you then have two claims. When the init method ends, you only have one reference to the instance, through the ivar/property -- you've lost the local variable -- which means that you have more ownership claims than you have references. This is a good indication that you will have a leak.
To fix the leak, you need to relinquish one of your claims before the end of the init method. You can do this in one of two ways, using release as soon as the property is set:
DoublyLinkedList * dll = [DoublyLinkedList new];
[self setDoublyLinkedList:dll];
[dll release];
or autorelease:
[self setDoublyLinkedList:[[DoublyLinkedList new] autorelease]];
// Or equivalent procedures involving a temp variable
However, it should be noted that using setters in init may be problematic (see also Mike Ash's writeup on the topic), because accessors can -- potentially -- have side effects that depend on your object already being fully set up. There seem to be two camps on this issue, and it's probably best to read about it and come to your own conclusions, but you may find that it simplifies your initializer methods to assign to ivars rather than using properties:
if( self ){
doublyLinkedList = [DoublyLinkedList new];
}
This is completely correct in terms of memory management.
Finally, if DoublyLinkedList is a class whose code you have, you can also consider writing a convenience constructor, which will return a new, autoreleased instance for you. The convention in Cocoa is to simply name the method after the class, with standard method name casing, like so:
+ (id) doublyLinkedList {
return [[[self alloc] init] autorelease];
}
Note that this is a class method:
if( self ){
[self setDoublyLinkedList:[DoublyLinkedList doublyLinkedList]];
}
and see my answer to "Self-allocating objects" for an explanation of these constructors.

If you have a property called "doublyLinkedList" (assumption based on code given), and it is "retained," you can do the following:
if (self) {
DoublyLinkedList *dll = [[DoublyLinkedList alloc] init]
self.doublyLinkedList = dll;
[dll release];
}

Related

Do I need to release my singleton object?

I have a singleton object in my app:
+ (id)shared {
#synchronized(self) {
if (sharedDownloadFirstData == nil)
sharedDownloadFirstData = [[self alloc] init];
}
return sharedDownloadFirstData;
}
- (id) init {
if (self = [super init]) {
}
return self;
}
And I want to know if I need to realese it (I am not using ARC). To do that I am using:
[[DownloadFirstData shared] release];
Did I need to release this object? I have an array and other stuff in the object that I need to release.
In Objective-C, you should only ever call release on an object you own. This typically means an object you've created with alloc, init, copy or mutableCopy or otherwise called retain on. Here, the consumer of [DownloadFirstData shared] didn't call any of those functions and is not responsible for releasing it. You will see this any time you call [UIColor blackColor], for instance.
You may want to call retain on such an object, if you are crossing autorelease boundaries or are just not sure of the lifetime:
DownloadFirstData *local = [[DownloadFirstData shared] retain];
...
[local release];
In this case, you've taken ownership and are responsible for releasing.
But what about the definition of shared? When you define a method not using init..., you are typically responsible for leaving with a release count of 0, with something like [[self alloc] init] autorelease]. This is not the case for the singleton because your goal is for it to always exist and therefore always have a non-zero retain count. You make this happen simply by not releasing it after you create it.
there is no sense in having a singleton if you will release it.
Usually a singleton is created because you want the same object till the app ends.
At the end of your app life cycle all memory related to the app is freed.
Use a standard approach, if you need alloc release often.
if your singleton takes a lot of memory, you should consider to write it better.
anyway, [[DownloadFirstData shared] release]; will work.

Objective-C Property assignment without #property

I'm currently developing an iOS application which was started by another developer.
Usually, I make a property for every instance variable (assign for int, bool etc. / retain for all classes).
So in my projects, this line causes a leak:
myVar = [[NSString alloc] init]; (alloc/init +1, retain in setter +1, release in dealloc -1 => +1)
So I use:
NSString *tmpMyVar = [[NSString alloc] init];
[self setMyVar: tmpMyVar];
[tmpMyVar release];
Or:
NSString *tmpMyVar = [[[NSString alloc] init] autorelease];
[self setMyVar: tmpMyVar];
In this new project, the previous developer didn't use #property/#synthesize so I'm wondering what will be the result of the previous line of code in this context (it doesn't call setter I guess)? Memory Leak?
The previous developer releases variable in dealloc method, just like me.
Thank you very much!
Since it directly assigns the instance variable to the allocated object it's retain count is 1 (because, like you said, a setter isn't called).
And because it's released in dealloc, it's all balanced out. So no memory leaks.
So in my projects, this line causes a leak:
myVar = [[NSString alloc] init]; (alloc/init +1, retain in setter +1, release in dealloc -1 => +1)
No,it wouldn't even in your projects, because, as you pointed out, no setter is used.
Also, when using properties, it is the recommended way to access instance variables directly in the init method, instead of using setters.
To inspect for questionable memory-leaks like your example, also use the clang static analyzer or instrument's leak tool.
You need to look at the other developer's setter implementation. Make sure they release the existing value and retain the new value; something like:
- (void)setMyString:(NSString *)string
{
[string retain];
[_string release]; // ivar
_string = string;
}
The only advantage to implementing your own setter/getter methods is to do something (other than setting the ivar) when a value is set. If the methods don't do anything like this then why not change all implementations to #property/#synthensize?

Managing Memory in Objective c

I am doing my project in xcode 4.2 (Older Version). For my application, I just set the variables, arrays in dto class for using in entire app lifecycle. so I set with a property like this.
AppDTO(sub class of NSObject)
AppDTO.h
#property(nonatomic,retain)anotherAppDTO *aAppDTO;
#property(nonatomic,retain)NSMutableArray *array1;
#property(nonatomic,retain)NSMutableArray *array2;
#property(nonatomic,retain)NSString *string1,*string2,*string3;
AppDTO.m
- (id)init
{
self = [super init];
if (self) {
self.aAppDTO = [[anotherAppDTO alloc]init];
self.array1 = [[NSMutableArray alloc]init];
self.array2 = [[NSMutableArray alloc]init];
self.string1 = #"Hello";
self.string2= #"Hai";
}
}
-(void)dealloc
{
if(array1 != nil)
{
[array1 release];
array1 = nil;
}
if(array2 != nil)
{
[array2 release];
array2 = nil;
}
[aAppDTO release];
aAppDTO = nil;
[super dealloc];
}
when I analyze my app in Xcode 4.3.2, I get memory warning in self.array1 and self.array2 (Potential leak on object allocated on line….), but when I change self.array1 to array1, warning goes away.
What is the reason for using self. do I need to use self if I set #property(nonatomic,retain) to variables(like array1,array2,string1,string2).
Also in dealloc method, I heard we don't want to use [self.array1 release], instead we can use [array1 release]. Is it Correct?
Do I need to release my string in dealloc method.
Also I am releasing aAppDTO in dealloc method. if I allocate some objects in anotherAppDTO class, will it release automatically when I call [aAppDTO release] method.
Can anyone clarify me.
Many Thanks,
Anish
You get the warning because when you write :
self.array1 = [[NSMutableArray alloc]init];
is the same as :
[self setArray1: [[NSMutableArray alloc]init]];
As you can notice you are not allocating the underlying array1 private variable, but you are calling the setter of the property that since it is declared as retain it retains the object once assigned, this means that when you eventually will assign another object the second time with the setter the first object will remain with a retain count of one until the application will be closed (since you don't have any reference to that object anymore ...) .
Take a look at this great article to understand better Manual Reference Counting in Objective-C .
when i analyze my app in Xcode 4.3.2, i get memory warning in self.array1 and self.array2 (Potential leak on object allocated on line….), but when i change self.array1 to array1, warning goes away.
the analyzer's right. the parameter is retained when set. as well, you should favor direct access in initialization and dealloc. so, you should just write array1 = [[NSMutableArray alloc] init];, and be done.
What is the reason for using self. do i need to use self if i set #property(nonatomic,retain) to variables(like array1,array2,string1,string2).
those go through the accessor methods. if not in initialization or dealloc, you should favor going through the accessor methods because that is the common correct execution path for a fully constructed object.
Also in dealloc method, i heard we don't want to use [self.array1 release], instead we can use [array1 release]. Is it Correct?
correct.
Do i need to release my string in dealloc method.
yes.
Also I am releasing aAppDTO in dealloc method. if i allocate some objects in anotherAppDTO class, will it release automatically when i call [aAppDTO release] method.
when its reference count reaches 0, its dealloc will be called.
I think the others have answered your question.
I do want to draw your attention to Apple's excellent Advance Memory Management Programming Guide: Practical Memory Management, in which they walk through these sorts of scenarios. It's hard to take it all in on the first reading, but it really does cover this stuff. In answer to your question about the use of instance variables versus the accessor methods, I draw your attention to the section labeled to "Don't Use Accessor Methods in Initializer Methods and dealloc".

Why always leak when using CLLocationManager?

myclass.m
- (id) init {
self = [super init];
if (self != nil) {
self.locationManager = [[[CLLocationManager alloc] init] autorelease];
self.locationManager.delegate = self; // send loc updates to myself
}
return self;
}
- (void)dealloc {
[locationManager release];
[super dealloc];
}
I use instrument to check leak. The leak always point to
self.locationManager = [[[CLLocationManager alloc] init] autorelease];
Why?
I use instrument to check leak. The
leak always point to
self.locationManager = [[[CLLocationManager alloc] init] autorelease];
Why?
Because that is the line of code where the allocation that is leaked occurred. Since you have balanced both implied retains in that code correctly (once here, once in -dealloc -- mmccomb's suggestion of direct assignment without autorelease is good, but won't fix the problem), the leak is elsewhere.
Specifically, the leak will be a retain that isn't balanced by a release. So, somewhere your are retaining the object and not releasing it.
Instruments can be used to show all retain/release events on any given object. Use that and look through the list of events related to your leaked object. There will be one more retain than release. Pair off the retains and releases. Whichever retain is left without a balanced release is the cause.
I wrote an article about using Heapshot analysis in Instruments to detect memory abuse. It includes discussion and screenshots showing the retain/release event inspector and will be applicable.
Try to avoid using the self. setter notation in init methods. When an object is being initialised there is no guarantee that it is in a consistent state. Change your implementation to directly set the ivar as follows...
locationManager = [[CLLocationManager alloc] init];
You no longer need the autorelease call which was previously accounting for the extra retain count brought about by invoking the setter. You do however need to release the object in your dealloc method (as you are already doing).
You can explicitly check the retain count in dealloc like so:
NSLog(#"locationManager retain count: %d", [locationManager retainCount]);
If it is more than 1, check where else you may be retaining it - like if you assign it to another retaining property (e.g. declared with retain keyword). You can add that NSLog call in other locations before and after you do something with locationManager and see where the retain count increases. Sometimes it may not be immediately obvious.
Another possibility: does the dealloc method even get called? Perhaps the whole "myclass" object is not properly released? (Although I suppose in that case you'd see a leak of type "myclass", too).

Assigning to self in Objective-C

I'm from the C++ world so the notion of assigning this makes me shudder:
this = new Object; // Gah!
But in Objective-C there is a similar keyword, self, for which this is perfectly acceptable:
self = [super init]; // wait, what?
A lot of sample Objective-C code uses the above line in init routines. My questions:
1) Why does assignment to self make sense (answers like "because the language allows it" don't count)
2) What happens if I don't assign self in my init routine? Am I putting my instance in some kind of jeopardy?
3) When the following if statement fails, what does it mean and what should I do to recover from it:
- (id) init
{
self = [super init];
if (self)
{
self.my_foo = 42;
}
return self;
}
This is a topic that is frequently challenged by newcomers:
Wil Shipley: self = [stupid init];
Matt Gallagher: What does it mean when you assign [super init] to self?
Apple documentation: Implementing Initializers
Cocoa-Dev: self = [super init] debate
Basically, it stems from the idea that a superclass may have over-ridden the designated initializer to return a different object than the one returned from +alloc. If you didn't assign the return value of super's initializer into self, then you could potentially be dealing with a partially initialized object (because the object that super initialized isn't the same object that you're initializing).
On the whole, it's pretty rare for super to return something different, but it does happen in a couple of cases.
In Objective-C, initializers have the option of returning nil on failure or returning a completely different object than the one the initializer was called on (NSArray always does this, for example). If you don't capture the return value of init, the method might be executing in the context of a deallocated object.
Some people disagree about whether you should do the whole assign-to-self rigamarole if you don't expect to get something else back from the superclass initializer, but it's generally considered to be good defensive coding.
And yes, it looks weird.
It is true that init may return nil, if the initialization fails. But this is not the primary reason why you should assign to self when you implement your own initializers.
It has been mentioned before, but it is needed to stress even harder: the instance returned from an initializer may not be the same instance as the one you sent in, in fact it may not even be of the same class!
Some classes use this as a standard, for example all initializer to NSString and NSArray will always return a new instance of a different class. Initializers to UIColor will frequently return a different instance of a specialized class.
And you yourself can happely implement something like this if you want:
-(id)initWithName:(NSString*)name;
{
if ([name isEqualToString:#"Elvis"]) {
[self release];
self = [[TheKing alloc] init];
} else if (self = [super init]){
self.name = name;
}
return self;
}
This allows you to break out the implementation of some special case into a separate class, without requiring the clients of your API to care or even know about it.
All the other points here are valid, but it's important for you to understand as well that self is an implicit parameter to every Objective-C method (objc_msgSend() passes it) and can be written to, just like any other method parameter. (Writing to explicit parameters is generally frowned upon, unless they are out parameters.)
Typically, this is only done in the -init method, for the reasons others have stated. It only has any effect because self is returned from the method and used in the assignment id obj = [[NSObject alloc] init]; It also affects the implicit resolution of ivars, because, for example, if myVar is an ivar of my class, then accessing it in a method causes it to be implicitly resolved to self->myVar.
I'm still new to Objective C, but this post helped me in understanding this.
To sum it up, most init calls return the same object that self is already initialized to. If there is an error, then init will return nil. Also, some objects such as singletons or unique objects (like NSNumber 0) will return a different object than the one initialized (the singleton or a global 0 object). In these situations you need to have self reference that object. I'm by no means an expert in what is going on behind the scenes here, but it makes sense on the surface, to me.
If [super init] returns nil that means that you have been deallocated and your self parameter is now an invalid pointer. By blindly following the self = [super init] convention you will save you from potentially nasty bugs.
Consider the following non-typical initializer:
- (id)initWithParam:(id)param {
if (!param) {
// Bad param. Abort
self = [super init]; // What if [super init] returns nil?
[self release];
return nil;
}
else
{
// initialize with param.
...
}
}
Now what happens if my superclass decides to abort and return nil? I have been de-allocated and my self parameter is now invalid and [self release] will crash. By re-assigning self, I avoid that crash.