objective-c over-releasing in dealloc - iphone

Is mystring over-released?
-(void)dealloc {
[mystring release];
[mystring release];
[super dealloc];
}
I assume this will not based on [nil release] does nothing:
-(void)dealloc {
[mystring release];
mystring = nil;
[mystring release];
[super dealloc];
}
-EDIT-
Let's say I allocate mystring in init and release it in doSomething:
-(id)init {
if (self = [super init]) {
mystring = [[NSString string] retain];
}
return self;
}
-(void)doSomething {
[mystring release]; // for some good reason
// ...etc
}
Now to avoid over-releasing in dealloc based on my example above do I have to explicitly do this in the doSomething method?
-(void)doSomething {
[mystring release];
mystring = nil; // <- is this mandatory to avoid over-releasing in dealloc?
}
The big question is do I have to explicitly set it to nil when I release it somewhere else in the class to avoid over-releasing in dealloc?
So could I do as many releases as I want in dealloc based if I explicitly set to nil in doSomething?
-(void)dealloc {
[mystring release];
[mystring release]; // <- does nothing because mystring explicitly nil?
}

For your first example, the answer is probably!
In general, each object that holds a reference to another object should retain it until they're done, then call release once, however in some highly exotic (and generally poorly written) cases this may not hold. If you retain the object x times, you need to release it x times, and other cases of poor memory management. But best practice, yes, one retain, one release, don't release more than you retain!
There are two risks with over-releasing like this:
The first is if the first release call makes the refcount of mystring equal to 0, it will be dealloc'd, and then you're sending a message to a piece of memory that is no longer a valid object. Objective-C doesn't really like this, and may react in a variety of ways, including CRASHING. Sending messages to nil, kosher, messages to things dealloc'd, not so much.
The second is if the refcount isn't zero, you just released someone else's reference, so at some point in the future, an object that has a reference to mystring may think that reference is valid and it won't be because it was dealloc'd when the refcount hit zero on a subsequent release call. This will be harder to detect than the previous error, where a debugger will at least show you the real area the problem originates from in the stack frame trace.
Your second example is correct - sending a message to nil does nothing. If you fear you'll do things like this, be sure to set your variables to nil after releasing.
EDIT: Yes. That's what you should do if you intend to release in more than one place like that, however depending on the application, you might consider using an auto-release pool.

It all depends on how many time you retained mystring. If you have two members that may refer to the same object and both retain the object, they should both release the object.
So your first example would be correct if you use mystring = [[somestring retain] retain];

The second one will be better. Because when you release, you release the memory the mystring point to not the memory of the mystring. So, the mystring is not null and if somebody accidentally use it, your app will crash. It also depends on how many times your mystring is retained

Related

#property/#synthesize question

I'm going through all of my documentation regarding memory management and I'm a bit confused about something.
When you use #property, it creates getters/setters for the object:
.h:
#property (retain, nonatomic) NSString *myString
.m:
#synthesize myString
I understand that, but where I get confused is the use of self. I see different syntax in different blogs and books. I've seen:
myString = [NSString alloc] initWithString:#"Hi there"];
or
self.myString = [NSString alloc] initWithString:#"Hi there"];
Then in dealloc I see:
self.myString = nil;
or
[myString release];
or
self.myString = nil;
[myString release];
On this site, someone stated that using self adds another increment to the retain count? Is that true, I haven't seen that anywhere.
Do the automatic getters/setters that are provided autorelease?
Which is the correct way of doing all of this?
Thanks!
If you are not using the dot syntax you are not using any setter or getter.
The next thing is, it depends on how the property has been declared.
Let's assume something like this:
#property (nonatomic, retain) Article *article;
...
#synthesize article;
Assigning something to article with
self.article = [[Article alloc] init];
will overretain the instance given back by alloc/init and cause a leak. This is because the setter of article will retain it and will release any previous instance for you.
So you could rewrite it as:
self.article = [[[Article alloc] init] autorelease];
Doing this
article = [[Article alloc] init];
is also ok, but could involve a leak as article may hold a reference to an instance already. So freeing the value beforehand would be needed:
[article release];
article = [[Article alloc] init];
Freeing memory could be done with
[article release];
or with
self.article = nil;
The first one does access the field directly, no setters/getters involved. The second one sets nil to the field by using a setter. Which will release the current instance, if there is one before setting it to nil.
This construct
self.myString = nil;
[myString release];
is just too much, it actually sends release to nil, which is harmless but also needless.
You just have to mentally map hat using the dot syntax is using accessor methods:
self.article = newArticle
// is
[self setArticle:newArticle];
and
myArticle = self.article;
// is
myArticle = [self article];
Some suggestions on reading, all official documents by Apple:
The Objective-C Programming Language
Dot Syntax
Declared Properties
Memory Management Programming Guide
Object Ownership and Disposal
Using Accessor Methods
When you create a retain setter, you're creating something like this:
- (void)setString:(NSString *)someString {
if (someString != string) {
[string release];
[someString retain];
string = someString;
}
}
If you don't use the setter, the new value is not getting that retain—you don't "own" that string, and because it's all references, if the original string is released, you might be facing a null reference, which will lead to an EXC_BAD_ACCESS. Using the setter ensures that your class now has a copy of that value—so yes, it does increment the retain count of the new value. (Note that using the getter is a convention of OOP—that outsiders should not be able to directly touch the ivar. Also in your getter you can modify the value, maybe returning an NSArray when your ivar is an NSMutableArray, for example).
You shouldn't autorelease in a setter—Apple has used it in their sample code, but a thing to keep in mind is that setters are called a lot—millions of times, potentially. All of those objects are going into the same autorelease pool, so unless you create your own and/or regularly flush it, you'll have a ton of elements in your pool, all unneeded but still taking up RAM. Much better to simply release.
As for dealloc, trace back through that setter. If you send a release directly, it's obvious—you release that object. But if you write self.string = nil;, what you're doing is this:
The nil value is not the same, so you enter the if block
You release the old value—what you want to do
You retain nil: messages to nil do nothing, and you don't crash
You set nil, which doesn't take up any memory, to the string, which is now effectively empty
As a matter of convention, I use release in my dealloc method, because release seems more final, and dealloc is the final method call your object will receive. I use self.string = nil; in viewDidUnload and the memory warning methods.
Hope this helps!
In addition to Nick's answer - synthesized getters/setters don't provide autorelease (btw, what's the big idea of doing this? Well, you can use getter as a factory, but it's not a common way in Objective C).
Then in dealloc I see:
self.myString = nil;
or
[myString release];
or
self.myString = nil; [myString
release];
In dealloc it doesn't really matter which form of release you're using. But the good way is to nil your fields when releasing them :) I prefer to use self.myString = nil; in dealloc

iPhone memory management: a release after setting self.someProperty = nil

I am reading the LazyTableImages code that Apple have released and they do something to this effect (in an NSOperation subclass):
- (void)dealloc {
[myProperty release];
[myProperty2 release];
}
- (void)main {
//
// Parse operation undertaken here
//
self.myProperty = nil;
self.myProperty2 = nil;
}
My thinking is that they do this in case dealloc is called before setting properties to nil.
Is my thinking correct here? Are the releases unnecessary, as self.myProperty = nil effectively releases myProperty?
One thing I have noticed in this code is that they don't release all retained objects in dealloc, only some of them, which is really the cause for my confusion.
Cheers
You can't do self.myProperty = nil or even [myProperty release] after dealloc. Know why? Because self doesn't exist any more.
As for your question, it appears that the releases in dealloc are unnecessary, but it's still good practice to clean up your instance variables in your dealloc method.
edit
As Peter points out in the comment, if the -main method is never executed, then having the release statements in -dealloc is necessary; without them, you'd be leaking memory.

What's the best way to release objective-c properties?

I'm new to memory-management, and am reading different things about how to best release properties.
If I have:
in .h:
#property(retain) NSString *myStr;
and in .m:
#synthesize myStr = _iVarStr;
Should my dealloc have:
[_iVarStr release];
or
self.myStr = nil;
or something else?
Thanks!
Both self.myStr = nil and [myStr release] ultimately do the same thing.
Calling [myStr release] is obvious and just releases it.
Meanwhile, the setter method for myStr looks roughly like this:
- (void)setMyStr:(NSString *)newMyStr
{
[newMyStr retain];
[myStr release];
myStr = newMyStr;
}
So when we do self.myStr = nil, we're first retaining a nil object, which does nothing. Then we release the old variable, which is what we want. Finally, we set the pointer to nil.
What's the difference? The latter sets the pointer to nil. This is better because if we (accidentally) send a message to the released object, we crash if the pointer isn't nil (EXC_BAD_ACCESS). Now honestly, since you're in -dealloc, the object is being destroyed anyways, so it wouldn't really matter what you use.
When a property is set to retain then
self.ivar = nil;
will properly manage the memory allocation. For other property types check the at the official documentation page. It also has a bunch of sample code so you can understand what happens "under the hood" for all the options.
Your dealloc should be this:
- (void)dealloc {
[_iVarStr release];
[super dealloc];
}
Although setting the property to nil is possible, I worry about unintended side effects or KVO actions triggered by the change that may not realize the object is currently being deallocated.
I recommend you use self.ivar=nil(the code ivar=nil previously I wrote was wrong) way in dealloc method. Because, if the ivar's property change from retain to assign (or from assign to retain), you don't have to change your code.

What is the best way to dealloc memory in Objective C?

I have a query regarding the memory management.
Let's begin with an example. Assume we have a class as follows.
#interface myClass : NSObject {
NSString *xyz;
}
#end
Now, see the implementation.
#interface myClass : NSObject {
NSString *xyz;
}
#end
#implementation myClass
-(void)abc{
// xyz allocted here
}
-(void)pqr{
// retained or copied many times or may not a single time
}
-(void)mno{
// retained or copied many times or may not a single time
}
-(void)jpg{
// may be released more than one time or may be not
}
//-(void)dealloc{
// [xyz release];
// [super dealloc];
//}
//
//-(void)dealloc{
// if(xyz!=nil && [xyz retainCount]>0){ [xyz release]; xyz=nil; }
// [super dealloc];
//}
-(void)dealloc{
if(xyz!=nil){
while([xyz retainCount]>0)
[xyz release];
xyz=nil;
}
[super dealloc];
}
#end
In above code. I have three dealloc functions. Which one is preferable? If none of these, then please suggest yours.
I am confused because Objective C says, object must be released each time = each time alloc/retained.
But most of the sample code has just single statement "[xyz release];" doesn't it create a memory leak?
This is absolutely wrong:
while([xyz retainCount]>0)
[xyz release];
xyz=nil;
retainCount will never return 0, because as soon as you are at a retainCount of 1 and the object is released, the runtime just deallocates it right then and there, never decrementing the retainCount. Even if it did decrement the retainCount, the object is now deallocated. How are you going to ask it what it's retainCount is?
In a nutshell, your design is wrong. If you can't keep track of how often you've retained an object in a smarter way, then you will have memory leaks and most likely crashes from overreleasing objects (this while loop will crash your app).
If you absolutely can't change your code (I wouldn't believe you if you said you couldn't), then you'd want to keep a second integer ivar indicating how many times you've retained xyz, and then use that to figure out how many times you should release it. (However, this should be an absolute last ditch effort, as in Armaggeddon will happen if you don't get this working in 30 seconds. You should really refactor your code first.)
In addition, you've forgotten the call to [super dealloc] in your dealloc method.
- (void)dealloc {
[xyz release];
[super dealloc];
}
...is the correct version. In Objective-C, you generally shouldn't use the retainCount method.
If you want to be very safe, you can also write:
- (void)dealloc {
[xyz release], xyz = nil;
[super dealloc];
}
The idea is that myClass has a member variable (in your case, xyz). When a myClass object gets created, it should create (or get a reference to) xyz by adding only 1 to the retain count (whether through retain or other means depends on the situation).
It would not be a good idea in each method to retain xyz with releasing it again. So at the end of each method, the the local object should have no more holds on xyz than it had at the beginning of the method.
By the time dealloc gets called, only that single retain hold should remain on xyz (as far as the myClass object is concerned), so a single call to release will suffice. It is not a good idea to release until the retainCount is zero because another object somewhere might be using it.
To directly answer your question, use this dealloc:
-(void)dealloc{
[xyz release];
}
objects those are retained during the poperty declaration need to be released in the dealloc method. So if you are declaring
#property(nonatomic, retain)NSString xyz;,
you need it to be released in dealloc as
-(void)dealloc{
[xyz release];
[super dealloc]
}
Any other allocated memory should be released immediately after the last use of that object from within your methods.
So if you are allocating xyz, in
-(void)abc{
// xyz allocted here
}
then you shoud release it at the end of the same method.
-(void)abc{
// xyz allocted here
// do something with xyz
//release xyz
example:
-(void)abc{
xyz=[[NSString alloc]init];//this may not be what you are following, but i just meant allocating memory
// do something with xyz
[xyz release]
//release xyz
In this case you need not release it in the dealloc method.
Also not that if you are property declaring xyz and retining it, you should not allocate it in your methods nor should release
while([xyz retainCount]==0)
[xyz release];
Should be > 0, otherwise the -release is not executed. Even so, deallocating xyz like this is a bad practice because xyz may be still owned by someone else.
You should allocate xyz one and only one time, and if you -copy it to replace xyz, always -release the old one. Always follow the Cocoa memory management rule.
If you really need to adopt multiple ownership to xyz, and a separate integer ivar to record how many times you have retained xyz, so you have the correct number to -release in -dealloc.

Why should I write [anView release], anView = nil; rather than [anView release];?

Somewhere I was reading that - regarding low memory warnings and giving up an non-visible view with all it's subviews (= a whole nib, I think), you should do that:
-(void)dealloc {
[anView release], anView = nil;
[someImageView release], someImageView = nil;
[super dealloc];
}
rather than
-(void)dealloc {
[anView release];
[someImageView release];
[super dealloc];
}
What's the reason for grounding those pointers to nil (= "no object"), after I call release? Let me guess: Some other method could have -retain'ed the view for some reason (anyone any example for when this could happen?), then the didReceiveMemoryWarning thing happens, and you release a whole nib+view that's currently not visible (i.e. in a multiview-app). As soon as the user wants to see that view again, you would quickly load the nib again and then: It loads all views, connects the outlets, and BANG! Your other retain'ed view's are hanging now without any pointer somewhere lonely in the memory brick, causing a fat and deep memory leak until your app crashes.
Right/Wrong?
The principle is more general than UIView. indeed it is more general than Objective-C/Cocoa -release method. It is valid also with C malloc()/free() memory functions.
When you no longer need an object or any memory zone, first you release/free it. Then, to make sure that you won't use it again, you clear the means to access this object or memory zone by assigning a nil to an object or a NULL to a memory pointer.
Some other method could have -retain'ed the view for some reason
Unless you're invoking dealloc yourself, it's only called when the retain count becomes zero.
Note that in Objective-C sending a message to a nil "object" is (often) perfectly fine. Doing so will not make your program halt, but the message is simply ignored. However, you cannot send a message to a freed object, which would yield a crash.
So, the following would give you an error:
[anView release];
[anView doSomething];
But, this is in fact ok:
[anView release];
anView = nil;
[anView doSomething];
It's a matter of taste, but for the above, you might in fact prefer to crash your program, rather than wondering why doSomething is not executed...
See also Sending Messages to nil from Apple's Introduction to The Objective-C 2.0 Programming Language.
The -dealloc method is called when the object is freed and no other methods on the object will be executed after. Therefore, setting any instance variable to nil has no effect outside that object.
If you were releasing an object (without using a setter) somewhere else in the class, it would be important to set the instance variable to nil to prevent code elsewhere from sending a message to that address.
I use this pattern a lot:
- (void) showHelp: (id) sender
{
if (helpController == nil)
{
helpController = [[HelpController alloc] initWithNibName: #"Help" bundle: [NSBundle mainBundle]];
}
[self presentModalViewController: helpController animated: YES];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
// Release anything that's not essential, such as cached data
[helpController release];
helpController = nil;
}
Pretty much everywhere that I allocate a viewcontroller that is modal, or otherwise "temporary". This way, it hangs around if I need it again, but goes away if memory gets low.
rather than doing the expicit release and set to nil, if your accessors have properties associated with them yoc and do the following as a more concise method:
- (void) dealloc
{
self.retainedProperty1 = nil;
self.retainedProperty2 = nil;
self.copiedProperty = nil;
self.assignedProperty = nil;
}
this way you can have code that has less repetition since the synthesized code will take care of your releases for you.
Edit: i should point out that your properties can't be readonly or else you get compiler errors for obvious reasons :)