iPhone - What happens if retain after autorelease? - iphone

Do you know what happens if I retain an autoreleased object ?
Will it be released or does the retain wins ?

Do you know what happens if I retain
an autoreleased object ? Will it be
released or does the retain wins ?
The retain "wins" but thinking of it that way is full of fail.
retain and release are merely mechanisms via which you increase or decrease the retain count of an object. Autorelease is simply a delayed release; no more, no less.
If you retain an autoreleased object you are increasing the retain count NOW while the retain count will be decreased LATER. This happens all the time; [NSString stringWithFormat: #"...."] returns an autoreleased string that you retain if you want it to stick around beyond [most typically] the current pass through the event loop.

If you want to keep your variable around, you need to retain it. For example:
myButton = [[UIButton buttonWithType:...] retain];
The buttonWithType: method returns a UIButton that's been instantiated with autorelease. It'll take care of releasing itself (so to speak) when needed.

The retain will win out. This is very common, and is an excepted practice.
Usually convenience methods return autoreleased objects like
[NSString stringWithFormat:#""];
It is expected that you retain whatever objects you need to, so long as you remember to release them later.
Remember that autoreleases will happen at the end of the current system message.
From the article below:
"an autorelease pool is created for each message that is processed by the system and the objects in the pool are all automatically released after processing on that message has completed."
Some great explanations of this can be found here:
http://www.iphonedevsdk.com/forum/iphone-sdk-tutorials/7295-getters-setters-properties-newbie.html

Related

Why is the retainCount still 1 after [object release]?

NSLog(#"first:%u",[object retainCount]);
[object release];
NSLog(#"second:%u",[object retainCount]);
Output:
first:1
second:1
Why doesn't the object get released?
a Quote from NSObject reference on retainCount method
This method is typically of no value
in debugging memory management issues.
Because any number of framework
objects may have retained an object in
order to hold references to it, while
at the same time autorelease pools may
be holding any number of deferred
releases on an object, it is very
unlikely that you can get useful
information from this method.
Object can be released but not when you think it will be. Basically, don't look at retainCount. It may not change until the next runloop or at all, it's an implementation detail. You will get a sense for when you need to release and when you don't with experience but until then rely on the clang analyzer.
First, retainCount doesn't give you a number you can use. It's meaningless.
Second, the reason the retainCount is 0 is probably that you try to work with an object that doesn't exist anymore. You're lucky your application doesn't crash, because your accessing invalid memory. Decreasing the retainCount just before deallocating an object is unnecessary, therefore Apple doesn't do it, probably.
Divide any number by zero and you will find the meaning of "object with retain count of zero".
I agree with the other comments about not using retainCount to get a reliable count.
EDIT: Ignore my stupidity below... :)
However, I've observed that setting the corresponding property to nil...
self.object = nil;
the retainCount does tend to be decremented immediately.

How many times do I release an allocated or retained object?

I am making an iPhone game. I want to release all objects that have been allocated or retained. In the dealloc function I am releasing all such objects, but then I realized that sometimes I end up releasing objects when they have not been allocated yet. So I figured I need to check if its retainCount is greater than zero or not before I release it.
My question is:
Do I just check if the retainCount is greater than zero and then release it?
if([bg retainCount]!=0)
{
[bg release];
}
or
Should I release it as many times as its retainCount
while([bg retainCount]!=0)
{
[bg release];
}
Thanks for your help!
Do not use -retainCount.
The absolute retain count of an object is meaningless.
You should call release exactly same number of times that you caused the object to be retained. No less (unless you like leaks) and, certainly, no more (unless you like crashes).
See the Memory Management Guidelines for full details.
Autorelease makes retainCount meaningless. Keep track of retains & whether you own an object. Study & remember these rules: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html#//apple_ref/doc/uid/20000994-BAJHFBGH

Is release without prior retain dangerous?

I have some code which I think has extra release statements.
Is the code incorrect?
What is the end result?
I don't understand memory management well yet - even after reading lots of articles and stackoverflow answers. Thanks for straightening me out.
Update: The attached snippet works fine, but other code has the over-release problem
NSMutableArray *points = [NSMutableArray new];
for (Segment *s in currentWorkout.segments) {
[points addObjectsFromArray:[s.track locationPoints]];
}
[routeMap update:points];
[points release];
Your code is correct, but inadvisable. new acts as an implied alloc, which creates the object with a retain count of 1.
I think the last time I used new was in 1992; it's not wrong, but alloc/init is considered better practice, because it is clearer what you are doing. Please read Apple's guide to memory management, it is a comprehensive summary of the situation.
No messages can safely be sent to a deallocated object. Once an object has been released a sufficient number of times, it's deallocated. Any further messages sent to that object are going to an object that isn't there anymore. The precise result isn't completely predictable, but it usually ends in a crash. If you're less lucky, it could end in much stranger ways — for example, you could theoretically wind up with an Object A getting dealloced early and Object B allocated in the same memory location, then Object B receiving messages meant for Object A that Object B does understand but isn't supposed to receive at that time.
Basically, follow the rules. Think of it in terms of ownership. If you've claimed ownership, you need to release that ownership. If you don't own the object, you must not release it.
Take a look at this article online: http://weblog.bignerdranch.com/?p=2 .
It seems to imply that calls to release without a corresponding preior call to retain will result in a BAD_ACCESS error.
A short answer is, if you increasing the retain count of an object and you no longer are using it you should release it, otherwise you shouldnt...
So when ever you do a [objectName alloc] you are increasing the count by 1, when you use such methods as [NSString stringWithString:] these methods return an autoreleased object so you dont need to release it...if you instead did something like [[NSString stringWithString:]retain] then you are increasing the strings retain count and you should release it after you are done using it.
Im not too sure if new increases the reference count (i suspect that it would), you can always check your retain count by doing [object retainCount]... though note that even if the retain count is greater than 0, it does not mean you need to release the object, because some other class might have a reference to the object and therefore has its retain count increased by one and its the responsibility of the other class holding the reference to release it.
Hope this helps
you should use:
NSMutableArray *points = [[NSMutableArray alloc] init];
[...]
[routeMap update:points]; //if routemap stores the points, it will need it's own release retain
[points release]; //if there is a retain in the method above, reference will not be cleared
if unsure, use the build->analyze command, it will search your code for leaked references
you can get the official memory management guide from https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/MemoryMgmt.html

Mem management for returned local variable

I am a little confused about retain/release count when a local variable is allocated within a method, then returned to its caller. For example
-(NSMutableString*)foo {
NSMutableString *str = [[[NSMutableString alloc] init] autorelease];
[str appendString:#"Just a test"];
return str;
}
NSMutableString *myString = [self foo];
Questions: (as you can see I am quite confused by this case)
1. Will str retain count increment when it is assigned to myString?
2. Is it safe to autorelease in this case?
3. Who should clean up the memory?
Thanks.
I would suggest you read the Cocoa memory management guidelines. All your questions are answered in there.
To answer about this particular code example: It's managing memory properly. This is what autorelease is for — where you need an object to stick around past a particular method invocation but still get released. You essentially turn ownership over to the autorelease pool.
And there's no magic to retaining and releasing. Assigning a local variable won't affect an object's retain count — it has to be sent retain or release for that to happen.
There's no special magic involved.
When a retain message is sent to an object, its retain count increases.
When a release message is sent to an object, its retain count decreases.
When an autorelease message is sent to an object, it adds itself to a pool.
When the pool is drained (which may be at the end of a run loop or thread), anything in that pool gets sent a release message.
When an object receives as many release messages as it has retain messages (assuming there's an implicit retain caused by alloc), the object sends itself a dealloc message.
The retain count of an object is otherwise untouched (barring any optimisations).
1) No
2) Yes - that's the correct pattern for this case. (You don't want callers to have to track and release this NSMutableString instance)
NSMutableString *str = [[NSMutableString alloc] init];
return str;
Would be bad because your caller is now forced to manage the returned variable.

iphone memory management issue

How to check if an object has been released from the memory?
I know a object has to be released manually when we use alloc|copy|retain to create that object. if use the instance class method (NSString stringwithformat:), the object will be released automatically by NSAutoRealeasePool, however, sometime there have some object used to release at the (void)dealloc function there.
Can anybody tell me
What is the difference between [object release] instantly after alloc function, [object release] at (void)dealloc,and NSAutoReleasePool to release the object?
When is the (void)dealloc function being called and when is the NSAutoReleasePool release the memory, I know it is every loop cycle, how can I check it from code?
When I declared a variable in the header and set the property as retain, I still can use the alloc function to that object but not cause a memory leak, but from this post it seems like once declared a retain object at header, then you no longer can alloc the object because both will retain the object,can anybody tell me why I still can code like this without causing any memory leak?
[object release] releases your object immediately. After sending a release message you should not use the object again - unless you absolutely know you still have a retain on that object. If yours was the last retain the memory could be freed during the call to release.
Autorelease frees an object 'sometime later' the system does not guarantee anything about the meaning of 'later' other than that it will be after the scope of the current message.
See above, there is no real qay to guarantee when dealloc is called following autorelease from the point of view of your code. You should just assume it is sometime after the return of the method where you send the autorelease message.
You simply need to balance retain and release. If you have one to many (as is likely i nthe situation you describe) that is a leak. Conversely if you have unbalance the other way, you will generate a more destructive error when you access freed memory.
The correct sequence for a retained property is:
alloc init // retain == 1
set the property // retain == 2 due to setProperty calling retain.
release the object // retain == 1
Which leaves a retain count of one, no memory leak.