I have a simple question. Does autorelease work when the retain count is high?
for example... If I am in a view controller and do the following:
[self retain];
[self retain];
[self retain];
[self retain];
[self autorelease];
If I pop the view, will it be released?
Thanks.
Autorelease simply adds the object to an autorelease pool. When the autorelease pool is deallocated a release message is sent to the object, and all the other objects in that pool. If your retain count is still greater than zero and you do no further releases, then you will have a memory leak.
I believe that if you do as you say above you will have a retain count of 5 (one from the alloc, and the 4 from the four retains you have above). You added the object to the autorelease queue so later it will receive a release and reduce the retain count by one. Finally popping the view should reduce it by one more. That would leave a retain count of 3. So I would think that you would have a memory leak.
However if you are using iOS 5, the latest compiler uses ARC (automatic reference counting) and you don't need to worry about this problem. Well for the most part.
EDITED: Corrected when objects are sent a release from the autorelease pool. See:
Advanced Memory Management Sorry for the wrong information.
Related
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is the difference between releasing and autoreleasing?
Hi can you please elaborate what is the difference between release and auto release and is there any way to create a user defined autorelease pool?and the real use of auto release pool.
Release reduces the object's reference count immediately, which means that if its retain count reaches zero it'll be immediately deallocated. Autorelease is a delayed release -- it's useful for ownership handoffs.
Consider a method like +[NSString stringWithFormat:]. It creates a new NSString instance (with alloc & some form of init) and then hands it off to the caller. That class method doesn't want to still "own" the created string after that, but if it releases the new string before returning, the new string will get deallocated before the caller gets it. Instead, it autoreleases the new string: that means the string will stick around long enough for the caller to grab it and retain it if needed.
What happens if the caller doesn't retain it? That's where autorelease pools come into play. The NSAutoreleasPool keeps track of every autorelease, and when told to drain, it releases all the objects in its pool (causing them to get deallocated if their reference count goes to zero). By default in a Mac or iOS app, there's an autorelease pool in the main event loop -- so if you call stringWithFormat: and don't retain the result, it'll go away on the next pass.
You can create your own autorelease pool with NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init] and drain it with [pool drain]. This can be useful if you have a section of code where you're creating a lot of temporary objects.
release releases the object immediately while autorelease does it some time in the future.
Example: You'd want to return an autoreleased object here, because if you'd release it, it would already get dealloc before the code calling this method can make use of the returned object!
- (NSObject *)someMethod
{
return [[[NSObject alloc] init] autorelease];
}
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
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
I am wondering if the autorelease pool holds strong or weak references to the objects it holds. I would guess they are weak. When I add an object to an autorelease pool, it's just not immediately released but will be released when the pool is drained, right? So the references should be weak, i.e. the reference count (or retain count) keeps the same when I add an object to an autorelease pool?
Talking of strong versus weak references makes sense in the context of a garbage collected memory management environment (where weak pointers are automatically released and cleared even if referenced). With GC enabled, all retain/release/autorelease calls are essentially do nothing operations (though the NSAutoreleasePool -drain method triggers garbage collection).
Now since you've tagged this question as iPhone related, and there's no garbage collection on iPhone, I'm assuming you're referring to regular reference counting, by strong you mean increasing the retain count of the referenced object, and by weak you mean just storing the pointer value.
The autorelease method essentially moves ownership of an object from the calling code to the current autorelease pool, you can think of the calling code calling release and the pool calling retain.
So the reference is effectively strong, but your code loses ownership and release responsibility. Object release will be called when the autorelease pool is released/drained.
The whole point of the autorelease pool is that it is a deferred release. For example, you can call autorelease on a local object you will be returning in a method so that it gets released even though you lose the reference to the object when the method returns.
Yes. retain count keeps the same, and yo can can check, that it is so:
id obj = [[NSObject alloc]init];
NSLog([NSString stringWithFormat: #"%d", [obj retainCount]]);
[obj autorelease];
NSLog([NSString stringWithFormat: #"%d", [obj retainCount]]);
The retain count remains the same, basically firing an autorelease message on an object makes the developer free from having the ownership and release responsibility.
This is how autorelease pool works-
Every time an instance of autorelease pool is created, it's added on top of the stack, so the most recent autorelease pool will be used by the system. And whenever you add any object in the autorelease pool, it's added on the top autorelease pool in the stack. An autorelease pool is basically an array on which the autoreleased objects are added. Every object added in autorelease pool is released when that particular autorelease pool is released(/drained). An autorelease pool is created first before the system starts processing any event, and it remains there till the current event loop's execution is over. When system see's that current event loop is completed then it get's the topmost autorelease pool associated with that event loop and releases it. Releasing an autorelease pool/ draining means getting each object added in autorelease pool and firing a release message on object, till all the objects in autorelease pool are released.
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.