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

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.

Related

Dealloc method isn't called when i release perticular object

I have created an object using alloc/init method, and after I release it -dealloc should be called immediately as per documentation. I set a breakpoint on -dealloc method but it isn't hit, and my -dealloc method is not called.
Please tell me what is the reason behind that, and what is use of dealloc method in objective c ?
The -dealloc method is not always called when you expect it to be called. The runtime might also have issued a -retain on your object for internal reasons.
It's also possible that you have (directly or indirectly) caused an extra -retain to be issued. If the retains/allocs and releases are not balanced, you'll never see -dealloc called. It helps to turn on the Static Analyzer, to make sure your calls balance.
Just follow the memory management rules, don't second guess the runtime, and let the memory management system do its job.
The answers to When does dealloc method call? may help you understand what you're seeing.
because it still has reference. that means its reference count not reached to zero. i don't know your code, where it is referencing. but it is not calling that means somehow still it has reference. it may be because of strong relationship or parent-child relationship
all Objective-C objects are allocated on the heap, so they must
therefore be deallocated somewhere if you are not to run out of
resources.
This gave way to the reference counting method, which is still used
today: each object keeps count of any references held to it. If you
receive an object and you want to keep it, you retain that object,
incrementing its reference count. When you are done with it, you
release it, which decrements its reference count. Once that count
reaches zero, it is inferred that no one is referencing the object and
it is automatically deallocated using the -dealloc method.
Additionally, an object could be told to “release at some point in the
(hopefully) near future” using autorelease pools. The idea is that
somewhere on the stack (typically at the start of a thread or while
responding to input events) an autorelease pool is created and pushed
onto a stack. Any object can then be sent an -autorelease message, and
it is assigned to that pool.
When the pool object is deallocated, it simply sends a -release
message to all its assigned objects. That way, any objects that are no
longer used (i.e. they haven’t been explicitly retained) are then
deallocated.
The dealloc is called (at more cases) whenever your object is released. You can't directly call this method.
#interface myViewController:UIViewController
{
NSString *myStr;
}
#end
Here the dealloc method in the #implementation of myViewController will be called (at most cases) when the myViewController object is released, not when myStr is released.
Although you don't have to use if you ARC.

ARC and memory management

I'm still not 100% with ARC internals.
A few examples that I would like clarified:
What happens with someObjectToReturn = [[SomeClass alloc] init]; that is allocated inside a method and returned? If someObjectToReturnis assigned to e.g. someObject, when will someObjectToReturn be released? When someObject is nilled or does someObjectToReturn still need to be added to an autorelease pool?
Another case is if an array of objects is nilled, are all the objects released?
Lastly, where is a good place to release a copied block object? Or will the block still be released after execution? If the copied block is added to an autorelease pool, when would one drain that pool?
Lets say there are 10 blocks, each added to an autorelease pool, draining it too soon would result in the executing blocks to die. Can a copied block be nilled from within itself, such as dispatching the nilling of the block back to the main thread?
You seem to be overcomplicating things. Under ARC, you can't release objects, or drain autorelease pools, so there is no "right" time to do this. Don't think about retain and release and autorelease (except in tight loops), think about object ownership.
Your specific questions:
The object will be released when the variable that the return value is assigned to goes out of scope or is set to nil. You don't have to worry about it.
Yes, all the contents of an array are released when the array is set to nil, you don't have to worry about it
You can set the value holding the copied block to nil when you're done, or it will disappear when the object owning the copied block goes. You can't drain an autorelease pool under ARC, you can wrap statements in an #autoreleasepool{} block, but this just captures everything in the block - you don't "add" things to the pool or "drain" the pool.

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.

When using autorelease, when is it actually released?

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.