When is an autoreleased object actually released? - objective-c

I am new in objective-c and I am trying to understand memory management to get it right.
After reading the excellent
Memory Management Programming Guide for Cocoa by apple my only concern is when
actually an autoreleased object is released in an iphone/ipod application. My understanding is at the end of a run loop. But what defines a run loop in the application?
So I was wondering whether the following piece of code is right. Assume an object
#implementation Test
- (NSString *) functionA {
NSString *stringA;
stringA = [[[NSString alloc] initWithString:#"Hello"] autorelease]
return stringA;
}
- (NSString *) functionB {
NSString *stringB;
stringB = [self functionA];
return stringB;
}
- (NSString *) functionC {
NSString *stringC;
stringC = [self functionB];
return stringC;
}
- (void)viewDidLoad {
[super viewDidLoad];
NSString* p = [self functionC];
NSLog(#"string is %#",p);
}
#end
Is this code valid?
From the apple text I understand that the NSString returned from functionA is valid in the scope of functionB. I am not sure whether it is valid in functionC and in viewDidLoad.
Thanks!

Yes, your functions are valid, and return objects using correct Cocoa conventions for retain/release/autorelease/copy.
To answer your question about what the runloop is, in your application's main() function, it invokes UIApplicationMain(). You can imagine UIApplicationMain looks something like this:
void int UIApplicationMain (int argc, char *argv[], NSString *principalClassName, NSString *delegateClassName) {
UIApplication *app = /* create app using principalClassName */;
[app setDelegate:/* create delegate using delegateClassName */];
while (![app shouldTerminate]) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
event = [app getNextEvent];
[app dispatchEvent:event];
[pool drain];
}
}
That while loops is similar to what the UIKit is actually doing, and each trip through that while loop is like a trip through the runloop, where the function getNextEvent blocks waiting for some event to happen. All of your methods are typically called from within something like dispatchEvent:. You might try setting a break point in one of your methods, like an IBAction, and looking in the debugger call stack way up at the top to see the names of the UIKit methods that handle the events and runloop. Since each of your methods are called from within that while loop, each time you call autorelease on an object, that object is added to that outter pool in the run loop. When the current event is finished being dispatched, the pool is drained, and those objects are finally sent release messages.
One last note. There can be more than one autorelease pool, that aren't always at the end of the event loop. Sometimes you might allocate tens of thousands of objects in one trip thorough the event loop. When that happens, you might setup additional inner auto release pools in your own methods to keep the number of autoreleased objects in autorelease pools down. Auto release pools can stack.

There's nothing wrong with that code. It will compile and run as you expect.
The NSString object returned from functionA is still valid upon return since it's being passed down the stack to the next guy (functionB) who is now keeping track of it.

Related

How to interact with #autoreleasepool

Based on Bavarious's answer to this SO question, I am led to believe that #autoreleasepool is now an Objective-C language feature if you build with LLVM/clang.
This being the case, how does one rewrite the following code to use an #autoreleasepool instead of an NSAutoreleasePool in a non-ARC environment?
[NSAutoreleasePool addObject:anObject]; // (*)
Background: I essentially want to write a custom implementation of -autorelease that does not in any way interact with the NSAutoreleasePool class:
#autoreleasepool {
SomeCls *obj = [[SomeCls alloc] init];
[obj autorelease]; // Does not go through an NSAutoreleasePool object
// ...
}
#autoreleasepool { } is a new language feature meant to obviate the need to drain the current pool at every exit point of a function. Now, instead of having to write:
void f(void) {
//Make a new pool
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
//Every inner scope that exits prematurely requires a drain
if (life_is_good) {
for (int i = 0; i < 1000; i++) {
NSObject *obj = [[[NSObject alloc]init]autorelease];
//breaks out of the loop, and the function, so drain the pool
if (life_is_bad) {
[pool drain];
return;
}
}
//Life gets bad below here, so return
[pool drain];
return;
}
//end of function requires drain.
[pool drain];
}
You can wrap the entire function in an #autoreleasepool { } directive and the compiler will insert the proper drains where the function returns:
void f(void) {
//Make a new pool
#autoreleasepool {
if (life_is_good) {
for (int i = 0; i < 1000; i++) {
NSObject *obj = [[[NSObject alloc]init]autorelease];
//breaks out of the loop, and the function, so drain the pool
if (life_is_bad) {
//[pool drain]; auto-drain
return;
}
}
//[pool drain]; auto-drain
return;
}
//[pool drain]; auto-drain
}
}
I have no idea why you would want to forgo the automatic pool mechanism, as it handles a huge amount of work for you (page management, per-thread pool management, releasing objects in a timely yet efficient manner), but it shouldn't be that much of a hassle to get a primitive NSAutoreleasePool up and running. Any autoreleasepool would require a page manager (malloc() and realloc()), pointer storage (a simple array), and some way to detect whether or not the current scope in which it is being used has exited (-drain). A simple pool could just be a thread-safe singleton, but be wary of how many objects you try to insert and remove at one time with that implementation. You just might segfault if you try to allocate too many hot pages for too many objects.
Based on Bavarious's answer to this SO question, I am led to believe that #autoreleasepool is now an Objective-C language feature if you build with LLVM/clang.
Correct.
This being the case, how does one rewrite the following code to use an #autoreleasepool instead of an NSAutoreleasePool in a non-ARC environment?
[NSAutoreleasePool addObject:anObject]; // (*)
Doc: Normally you don’t invoke this method directly—you send autorelease to object instead.
#autoreleasepool {
id anObject = ...;
[anObject autorelease];
}
Background: I essentially want to write a custom implementation of -autorelease that does not in any way interact with the NSAutoreleasePool class:
You can't even subclass NSAutoreleasePool any longer (in a meaningful way). Unless you never pass the object to other APIs which are free to autorelease, your objects are going to end up in the current autorelease pool. The mechanics of this today is not even object based.
If this is impossible, I would be open to workaround suggestions not involving NSAutoreleasePool.
Not certain what problem you are trying to solve, but you can extend lifetimes using:
NSMutableArray * fauxAutoreleasePool = NSMutableArray.new;
id anObject = ...;
[fauxAutoreleasePool addObject:anObject];
...
[fauxAutoreleasePool removeAllObjects]; // << explicitly drain, which also happens when the array is destroyed
Of course, you could write your own implementation. Why you would write your own is still a mystery, and not a good idea for production code (#autoreleasepool works well).
Though I have already marked an answer as accepted, and offered a bounty at the time, I have since found the true answer I was searching for and realised my question wasn't very clear - primarily because I didn't know what to ask.
How to interact with #autoreleasepool:
When the compiler comes across an #autoreleasepool { } block, it automatically inserts two function calls. At the opening of the block it inserts the C function call:
void *_objc_autoreleasePoolPush(void);
At the close of the #autoreleasepool block (including when a return or break is encountered within - but NOT when an exception is thrown according to the LLVM docs) the compiler inserts the C function call:
_objc_autoreleasePoolPop(void *ctxt); // ctxt is Apple's label for the param
I believe the void *ctxt parameter is an indicator of where the current #autoreleasepool started (really only useful in Apple's implementation - see here). In any case I found it can easily be ignored in custom implementations.
The -autorelease selector:
Essentially the methodology is this:
Create (if outermost block) or mark (if inner block) an autorelease pool object (in C or C++) in _objc_autoreleasePoolPush(). It seems easiest to me to use a Stack data structure for this but YMMV.
Ensure this object is in scope within the -autorelease selector, or you have a fail-safe way of accessing it.
Add the object to the autorelease pool object (in whatever way that may be) inside -autorelease.
In _objc_autoreleasePoolPop(void *), send the -release message to every item in the autorelease pool object until the marker set in _objc_autoreleasePoolPush() is reached (or you reach the bottom of the pool). Then do any additional required cleanup.
Final notes on threading:
Objective-C #autoreleasepools are supposed to be thread-local. That is, each thread has its own (if it requires one). As a result, _objc_autoreleasePoolPush() must have some way of determining whether the current thread already has an active autorelease pool and create the object if it does not.
Similarly, this is why, when creating a thread, the thread must first open an #autoreleasepool { } block before it does anything else (in Objective-C), and the final thing it must do is close that #autoreleasepool block (implicitly through break or return or with explicit fall-through).
Three final observations:
If you wish to implement your own autorelease pool object, you will need some form of thread-local storage to store it.
That last point about threading is why every Objective-C program must begin with an #autoreleasepool { } block in main().
This is why Apple ask you to use the NSThread class and GCD rather than DIY threading - they take care of all of this for you!
At the end of the #autoreleasepool block, the autoreleased objects are sent a release message.
If you want to reimplement the autorelease method, you may not want to directly send release messages to your NSObjectsubclass. If so, reimplementing release with some special behavior could do your business.
Background: I essentially want to write a custom implementation of
-autorelease that does not in any way interact with the NSAutoreleasePool class:
What makes you think that -autorelease interacts with NSAutoreleasePool?
As long as you are running on iOS 5+ or Mac OS X 10.7+, both the #autoreleasepool and -[NSObject autorelease] will use the runtime autorelease pool management functions, and have nothing to do with NSAutoreleasePool at all (and NSAutoreleasePool on those OS versions is simply a wrapper around the runtime functions).

Obj-c autorelease a variable up a chain of methods

I'm new to Obj-C and I have a question concerning the autorelease. Is it ok to return an autoreleased variable for several methods? For example:
- (void) methodC {
Object anObj = [self methodB];
//Do something with anObj
}
- (Object *) methodB {
return [self methodA];
}
- (Object *) methodA {
Object anObj = [[anObj alloc] init];
release [anObj autorelease];
}
Will the variable remain valid even if it is returned up a method chain and used at the top? Or does it have to be retained somewhere along the way?
thank you
Yes, it will be valid in this case. You only have to worry about the variable being deallocated if somebody drains the autorelease pool. As long as you've written every function that returns along the way and you don't explicitly drain the autorelease pool, you don't have to worry about objects being deallocated from under you.
In the vast majority of cases, the code in the NSRunLoop takes care of draining the autorelease pool. When you return control from your application code to the API code (such as by returning from a touchesBegan handler etc.), you don't know if the autorelease pool will be drained, so you have to assume in the worst case that it will. In that case, you have to retain any objects you want to keep references to.
For example:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
Object *anObj = [self methodC]; // Your methodC as before -- anObj is valid
[pool drain]; // anObj will be deallocated here
The variable should remain valid. You only need to retain an object if it is actually "owned" by some other object and could be indirectly/unintentionally released along with it. For example, if you extracted an object from an array and then released the array, your object reference could become invalid unless you explicitly retain it.
For more details, see Object Ownership and Dismissal, particularly the sections on Autorelease and Validity of Shared Objects. The latter uses the following code to illustrate how you could "accidentally" make an object reference invalid.
heisenObject = [array objectAtIndex:n];
[array removeObjectAtIndex:n];
// heisenObject could now be invalid.
The following code shows how to mitigate this problem using retain.
heisenObject = [[array objectAtIndex:n] retain];
[array removeObjectAtIndex:n];
// use heisenObject.
[heisenObject release];

Multithreading and autorelease pool

As I'm mastering my skills with multithreading with GCD, I've come across some question. Suppose you have the following method:
- (void)method {
NSString *string= [NSString string]; //will be autoreleased
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//very very lengthy operation...
NSLog(#"%#", string); //is it safe?
});
}
I'm wondering if this is correct, because I think I should have retained string before the block execution: in fact I fear that the event loop finishes and sends string an autorelease message before using string in the block. That would crash the program.
Am I right? Should I send a retain and a release message to string or this is the correct implementation?
Thanks in advance!
I'm wondering if this is correct, because I think I should have retained string before the block execution: in fact I fear that the event loop finishes and sends string an autorelease message before using string in the block.
Fear not:
A block captures the scope of the surrounding method/function in that it automatically retains any object-variable that is used inside of the block. Be aware of that when you use self inside of a block, as this may greatly affect the lifetime of the object!
There is one exception to this rule, and that are variables declared as
__block SomeObjectPointerType variableName
Update
Because there’s a new comment on this answer, I should probably add that things changed a little with the introduction of ARC:
Under ARC all object variables default to __strong, and this holds for variables marked with __block as well. If you want to avoid strong capturing of a variable in a block, you should define a local variable that is __weak.
End Update
If you like to learn more about blocks, bbum gave an excellent session called Introducing Blocks and Grand Central Dispatch on iPhone at WWDC 2010.
The "Block Details" section starts at 11:30.
The concern is; when an autorelease object releases?
NSString *myString= [NSString stringWithFormat: #"%#", stringVariable];
The myString depends upon stringVariable, whenever stringVariable releases the myString immediately releases.
NSString *myString= [NSString stringWithString: #"stringVariable"];
In practice it is observed the myString might be releases just after the completion of the method.
Now if you change your code and use NSAutoReleasePool
- (void)method {
NSAutoreleasePool pool = [[NSAutoreleasePool alloc] init];
NSString *string= [NSString string]; //will be autoreleased
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//very very lengthy operation...
// string will be released here
[pool release];
NSLog(#"%#", string); // it is not safe?
});
}
The autorelease objects released when the auto release pool releases in which they exists or when the object releases on which they depends.
Now if you are using the method in a thread you should use auto release pool inside it.
- (void)method {
NSAutoreleasePool pool = [[NSAutoreleasePool alloc] init];
// lengthy operations ...
[pool release];
}

Objective C - NSthread & NSAutoreleasePool?

What is the best way to write a thread safe method?
I have the following method, sometimes i want to call it asynchronously (call it through a thread)
And sometimes i want to call it directly on the main thread.
Is there a problem with keeping the pool (alloc, release) even if I am not calling the method on a separate thread?
- (void)doStuff
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
//do some stuff here?
[pool release];
}
That's perfectly safe to call on the main thread. NSAutoreleasePool maintains a stack, so in this case you're just putting a new pool on top of the stack, then popping it off when you're done.
No, there is no problem with always using your own, method-local pool. You should be using [pool drain] instead of [pool release], though.
Regardless of what it would mean for the release pool, I would not recommend writing it this way. If you absolutely have to be able to call the method from the main and from other threads, code it like this:
- (void) doSomething {
}
- (void) doSomethingInBackground {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
[self doSomething];
[pool release]
}
This way you wrap the method in a method that takes care of the release pool.
I will also prefer the method mentioned by Ivo Jansch. Creating/draining a pool is valid but it may be a bit headache when you call the method doStuff: recursively or many times. But by following Ivo's method you can do stuff without a memory headache.
And also for a method to be thread safe you must use locks or #synchronized() whenever its needed, usually when accessing a array/buffer/dictionary. Your method should be something like this
- (void)doStuff{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
#synchronized(lock)
{
NSLog(#"Hello World");
}
[pool release];}

Objective-C memory management: how do you release the memory when you return an allocated instance?

How do you release the memory in this situation? Do you have to?
- (NSString *) whatHappensHere {
NSMutableString * mutableString = [[NSMutableString alloc] initWithString:#"Hello"];
// ....
// more code ...
// ...
return mutableString;
}
With autorelease
- (NSString *) whatHappensHere {
NSMutableString * mutableString = [[NSMutableString alloc] initWithString:#"Hello"];
[mutableString autorelease];
return mutableString;
}
As willcodejavaforfood said, the convention is that any newly-allocated object returned from a method should be autorelease'd before being returned. This tells the Objective-C runtime that if nobody takes ownership of it with retain before (in most cases) the current iteration of the application event loop ends, it should be freed.
If it's just used locally in the calling function or returned up the stack, that works great and it gets freed sooner or later. If someone ends up wanting to keep it around, then they have to retain it and so will know they have to release it themselves later on.
(In fact, most of the non-init* utility constructors for ObjC base classes like strings, etc, do just that, or at least something functionally equivalent.)