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.
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];
}
Whenever we are calling autorelease method, its object is going to NSAutoreleasePool. When the pool is drained, it is sending release to all the objects in the pool.
My question is;
In the main function there is one NSAutoreleasePool. I want to know that; when we call the autorelease method, where it is sending the object ? I mean; it is sending the object to NSAutoreleasePool which is in main function (or) somewhere ?
Thanks in advance.
There is actually a stack of autorelease pools. Whenever you do [[NSAutoreleasePool alloc] init] that newly created pool is automatically put on top of the autorelease pool stack. You can create your own pools whenever you need it.
To be more precise: there is a stack of autorelease pools on each thread. So whenever you create a thread (for example with [foo performSelectorInBackground:#selector(bar) withObject:baz]) the very first thing you need to do is create a pool or else your objects leak (this creates the infamous messages like "NSAutoreleaseNoPool(): Object 0xd819d0 of class NSCFString autoreleased with no pool in place - just leaking" and is a very frequently asked question here on SO).
When you call autorelease, the object is registered with the top-most autorelease pool of the current thread (that is: the one that was created last on that thread). The main run loop has its own autorelease pool that is emptied on each run loop iteration (AFAIK). The pool from main.m is there to catch any objects that for example might be generated internally by Cocoa Touch before it gets to create the run loop autorelease pool.
Edit: For more behind-the-scenes information, see Mike Ash's "Let's Build NSAutoreleasePool"
If I have an object created as autoreleased, is there a way that I can mark it is essentially "not autoreleased"?
I feel that I have heard calling [object retain] will do what I am looking for but I am not sure.
Depending on what you really want [object retain] will do it...or nothing will.
If what you want is "my object should live past the drain of the autorelease pool", then [object retain] will do that for you. It will make the object live until you have a matching number of [object releases]s (or [object autorelease]s + pool drains).
If you want the object to not make the autorelease pool bigger, not to make the pool drain fractionally slower, or to make sure to object dies BEFORE the next pool drain, then [object retain] will not do it. In fact the only real way to do any of those things is to make sure the object never goes into the autorelease pool (or to a lesser extent, make a private autorelease pool and manage its lifecycle).
When an object is sent autorelease, it adds itself to the autorelease pool. At each iteration of the run loop, the autorelease pool is drained. It drains itself by sending it a release message to every object in the pool. If an object is added to the pool twice, it is sent two release messages, and so on. It is a very simple mechanic that greatly simplifies memory management.
If you have an object that has already been sent an autorelease message, then by sending that same object retain, you are cancelling out the effect of what will happen when the autorelease pool is drained.
Yes, calling [object retain] is exactly what you want.
I have a NSDictionary that is passed from the main thread to a second thread which retains, uses, then releases the variable.
What if the main thread autorelease pool is drained while the 2nd thread is still using the variable? Even though I have retained the variable in the 2nd thread, will the main thread's pool know that its still being used?
Thanks.
The autorelease pool is pretty dumb. It doesn't "know" that any variable is being used. It simply calls release on each autoreleased object. This generally occurs at the end of each iteration of the event loop.
If the autorelease pool is drained before your second thread has a chance to retain it, it will be deallocated. Instead, it's generally a good idea to retain anything that will be used in another thread before starting the thread. You have no way of knowing when the thread will run, so it's best to assume it won't run until after the autorelease pool is drained.
In other words, do something like this:
NSDictionary *dictionary = // Get the autoreleased dictionary... somehow
[NSThread detachNewThreadSelector:#selector(myThread:) toTarget:self withObject:[dictionary retain]];
Bear in mind your thread now owns dictionary and is responsible for calling release on it before the thread exits, or else your app will leak memory.
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.