When using autorelease, when is it actually released? - objective-c

Sometimes I wonder when something gets autoreleased. I added an NSLog in the dealloc of various objects, but I couldn't find anything useful.
When does something release when autorelease is used? Is it unpredictable, or is there some extra thread running? Thanks.

When the "autorelease pool expires".
What this typically means, is when the stack is unwound.
So think of it this way - your app is event driven. You get events sent to it - and they are processed through a series of functions. When each of the functions returns, and the event is done being processed, autorelease will be called.
This means you can count on a object to still be alive when you autorelease it, and return it from a function to it's caller. Don't ever expect it to be around when processing any kind of subsequent event, or when called outside you existing stack frame.

From the iOS documentation
Each thread in a Cocoa application maintains its own stack of NSAutoreleasePool objects. When a thread terminates, it automatically releases all of the autorelease pools associated with itself.

Related

Non-ARC library object sent to ARC code. Overreleased?

A non-ARC precompiled static library I'm using is sending my ARC app "event" NSObjects on my main thread, that it has placed in the main-thread's autorelease pool. My app acts on the event object in a handler function, but doesn't retain or release it, and doesn't use it again.
With Zombies on, I am occasionally getting a break when the main event loop drains the top level autorelease pool and one of these event NSObjects is being deallocated. It smells like ARC has already released the event object (perhaps when it went out of scope in my handler) and then the main event loop releases it again.
Is this a plausible theory, or is this impossible and I have another bug?
If it is possible, what can I do in my app to prevent this?
From your description, the autorelease works as it should - the function has autoreleased the object, meaning that you can use it but then it's released at the end of the auto release pool.
By default you use autorelease pool in the main loop. However nothing stops you from wrapping your call into #autorelease block and checking that the object is released at the correct time.

How to end a polling thread created with detachNewThreadSelector?

I'm creating a new thread using detachNewThreadSelector ref with toTarget self.
The purpose of the thread is to poll movements and load images as appropriate - it loops and only quits when an atomic bool is set to true in the main thread - which is set in the objects dealloc.
The problem is caused by this (from the detachNewThreadSelector reference):
The objects aTarget and anArgument are retained during the execution of the detached thread, then released
Which means my object will always have a (minimum) retain count of one - because the thread continuously polls. dealloc is therefore never called.
So my question is: how can I dealloc my object taking into account the existence of the polling thread?
The only idea I have right now is to create a destroyThread function of the object, which sets the end thread bool, which would be called from everywhere I'd expect the object to be destroyed. This seems error-prone, are there better solutions?
Thanks in advance.
Update
I had an idea for another solution - in the thread I detect if the retain count is one - if it's one then I know the thread is keeping the object alive, so I break the loop and dealloc is called. Is this a robust solution?
First, avoid detachNewThreadSelector:. Anything you are thinking of doing with it is almost certainly done better with a dispatch queue or NSOperationQueue. Even if you need to manually create a thread (which is exceedingly rare in modern ObjC), it is better to create explicit NSThread objects and hold onto them rather than using detachNewThreadSelector: which creates a thread you can't interact directly with anymore.
To the specific question, if you create your own threads, then you'll need to set that bool somewhere other than dealloc. That means that some other part of the program needs to tell you to shut down. You can't just be released and automatically clean yourself up using manual threads this way.
EDIT: Never, ever call retainCount. No solution involving retainCount is a good solution. Putting aside the various practical problems with using retainCount in more general cases, in this case it ties you manual reference counting. You should switch to ARC as quickly as possible, and retainCount is illegal in ARC (it should have been illegal before ARC, but they finally had a really good excuse to force the issue). If you can't implement your solution in ARC, it is unlikely a good solution.
Again, the best solution is to use GCD dispatch queues (or operations, which are generally implemented with dispatch queues). It is incredibly more efficient and effective for almost every problem than manual thread management.
If you must use a manual thread for legacy code and need to maintain this kind of auto-destruct, the solution is a helper object that owns the thread. Your object owns the helper object, which has a retain loop with the thread. When your object is deallocated, then it tells the thread to shut down, which breaks the retain loop, and the helper object goes away. This is a standard way of managing retain loops.
See Apple's Migrating Away From Threads for more.

Thread with lot of autoreleased objectIs is it mandatory to use autorelease pool on this scenario if yes/no why?

Consider we are implementing our own thread with lot of autoreleased object. Is it mandatory to use autorelease pool on this scenario if yes/no why?
It's mandatory to have an autorelease pool on any thread that you create, because Cocoa internals expect there to be one in place and you will leak memory if it isn't there.
Cocoa always expects there to be an autorelease pool available. If a pool is not available, autoreleased objects do not get released and your application leaks memory. If you send an autorelease message when a pool is not available, Cocoa logs a suitable error message.
Applications that link in Objective-C frameworks typically must create at least one autorelease pool in each of their threads.
It is mandatory even with a single autoreleased object, because otherwise it will leak.

Breakpoint pointing out "objc_autoreleaseNoPool"

So I'm debugging an app in preperation for its app so release, and I enabled a universal breakpoint for "All Exceptions". Since then, everytime I run the app, the console prints:
Catchpoint 2 (throw)Pending breakpoint 1 - "objc_exception_throw" resolved
objc[11765]: Object 0x8f18ff0 of class __NSCFLocale autoreleased with no pool in place - just leaking - break on objc_autoreleaseNoPool() to debug
objc[11765]: Object 0x8f190a0 of class __NSCFNumber autoreleased with no pool in place - just leaking - break on objc_autoreleaseNoPool() to debug
objc[11765]: Object 0x8f1fef0 of class __NSCFLocale autoreleased with no pool in place - just leaking - break on objc_autoreleaseNoPool() to debug
Literally printed 3 times. I have no idea what this means but it looks bad. Any advice would be appreciated.
New Info
I determined where my issue lies by creating a swizzled autorelease method.
I dont recommend doing that unless you know what you are doing, however this is what I found out.
+ (void) load; //Method is called outside the original autorelease pool.
+ (void) initialize; // Method is called outside the original autorelease pool.
NSThread creates its own thread, the called method should be wrapped in an autorelease pool.
Grand Central Dispatch takes care of adapting over the autorelease pool when using the "dispatch_..." commands. however, when you dispatch manually. you may want to wrap it in an autorelease pool.
Also, ARC does not handle letting you know that an autorelease will happen outside a pool.
Therefore if you are using ARC and know that you will be outside the autorelease pool. And there is nothing you can do about that. You will want to avoid all convenience methods.
use this.
[[NSString alloc] initWithFormat:#"%#",myObject];
instead of this
[NSString stringWithFormat:#"%#",myObject];
this will allow the arc system to retain and release, but the underlying autorelease done by the convenience method will be skipped as you will not have used the convenience method.
Hope that helps.
Original Answer
Ok, I dont feel this question was answered with enough detail.
the message being presented was
objc[1310]: Object 0x34f720 of class SimpleKeychain autoreleased with no pool in place - just leaking - break on objc_autoreleaseNoPool() to debug
The debugger is pointing out a possible breakpoint that will help you debug the situation. Now while this breakpoint really did little to help debug the situation. I think that it is important to know how to add that breakpoint to the debugger and so I spent the time tinkering with it (after scouring the internet and finding nothing) until I got it to break on that error.
It is kind of annoying that break on all errors does not catch this, but here are the steps to add the breakpoint to the debugger.
first thing you want to do is select the debugger's breakpoint navigator
by clicking on this tab
next you look toward the bottom of the navigator pane and press the Plus button
This will allow you to manually add a breakpoint.
I selected a C++ breakpoint and entered the message name into the name text field.
after adding this exception it did in fact break.
However this may or may not be useful to you as an objective c developer. This broke into the Assembly code.
Unfortunately it only showed this point on the call stack for the thread.
And it turned out that the autorelease problem was because a class called autorelease in a dispatch_once call. and further investigation revealed that the +(void)load; method on the class was called before anything else. this is done via the call_load_methods function and is outside the thread on the main method.
to correct this, I merely added the autorelease pool wrapper around the call.
another solution may be to add the autorelease pool inside the +(void)load; method. but this was sufficient for my uses.
NOTE: I am adding this to the post here because I do not like finding an issue and not being able to figure out all paths to the resulting answer. If the debugger tells you to add a breakpoint to the function listed, then there should be some information somewhere to get that information. Hopefully this will lower the frustration of some of those out there trying to find this answer.
Many of the methods in the cocoa api return autoreleased objects. In particular, those methods that return an object that don't begin with init, such as [NSNumber numberWithLong:]. If you don't have an autorelease pool in place, those objects will be leaked. You can find more information on using NSAutoreleasePool in the documentation.
It means you need to create an autorelease pool on the thread it happens. Otherwise, your allocated objects will not be destroyed (as suggested by the message). So, break/pause at the symbol, then walk up the stack to your thread (or program) entry and add an autorelease pool. That's all.

Objective C - Memory Management and autorelease ???

Does autorelease guaranty that at the end of blocks the object will get released?
Or is it better to manually release objects?
It guarantees it will be released sometime after the block executes, not necessarily immediately after. It's up to the runtime to determine exactly when.
It's not big deal unless you're doing something with a lot of autoreleased variables, like creating them in a big loop, or if you're creating large autoreleased objects, like UIImages. In these cases, you should manually release when you're through, otherwise autorelease is perfectly acceptable.
If an object is autoreleased, you MUST not manually release it (unless it is retained of course). The NSAutoRelease pool which is part of the UIKit event handler will release it for you. If you were to manually release the object, the pool may cause a crash or other undefined behavior as the object will be doubly-released.
If there are cases where you generate a lot of objects or use a lot of memory in objects, you can pre-emptively autorelease them (perhaps in your loop) by creating your own NSAutoReleasePool - pools can be nested.
It's better to release objects rather than autorelease, unless of course you have an explicit reason to use autorelease, for example use autorelease when returning an object the method retained and you can't avoid it.
Basically autorelease should be used as an excuse to completely avoid memory management. You want to release objects as soon as you possible can. Autorelease just says the object will be released some time in the future.