How best to debug a crash within objc_msgSend? - objective-c

I have a crash taking place when an NSAutoreleasePool drains. Presumably the pool is trying to deallocate an object that has been prematurely released by another piece of code. The crash I have is in the midst of objc_msgSend as it is trying to send a message to an object that doesn't exist anymore.
Given the stack state, what tips/tricks/processes/gdb commands do I have at my disposal to get information about the object in question and/or the point at which the illegitimate deallocation took place?

If you have a hunch that it is a premature deletion, enable zombies to confirm your hypothesis and then debug what is going on. When you enable zombies, objects are not really destroyed, but set to a zombie state, which helps you to detect when they are accessed after they dealloc is called. Read more from NSZombieEnabled

The definitive article on this kind of crash: http://www.sealiesoftware.com/blog/archive/2008/09/22/objc_explain_So_you_crashed_in_objc_msgSend.html

If you use NSZombieEnabled you can at least figure out what class the object is.

I came across what appeared to be a crash in objc_msgSend. What was even stranger was application:didFinishLaunchingWithOptions: was not even getting reached before the so called crash occured!
In my case the crash turned out to be a breakpoint that I had inadvertantly set on a memory address that was getting called before any of my code was even reached.
After the hour or so of trying to figure this out, I unchecked the breakpoint, ran the code, face palmed and then continued my day pretending it had never happened…

Related

-[CCSprite setPosition:]: message sent to deallocated instance, what now?

I´ve been having some problems with a bug that causes my game to crash. First it just gave me a "BAD_ACCESS" but by enabling Zombie objects the debugger said this:
-[CCSprite setPosition:]: message sent to deallocated instance xxxx
The crash happens when object A and B collides, but ONLY if the collision takes place at the same moment as object B is created.
Both A and B should be destroyed at collision, this works just fine except in the situation described above. I´m using Box2D for what it´s worth.
Is there any way to track the error in a more specific way? Like if it´s A or B that´s giving me trouble.
If you are using the simulator, enable MallocStackLogging and NSDebugEnabled. Then when you get this message, make note of the process id and memory address of the offending object. Then in your terminal, use malloc_history <pid> <memory_address> to see the history of allocs and deallocs of this address. It will give you a stack trace of each alloc and dealloc. The most recent alloc is probably the place where you've allocated something that you possibly didn't retain, or the most recent dealloc is the place where you dealloc'd it accidentally.
Heres the man page for malloc_history:
https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man1/malloc_history.1.html

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.

NSZombies enabled, debug information

My Mac app is crashing with exc_bad_access on the run loops.
So I enabled NSZombies, and Now I don't see such error as expected ( As the objects are not de-allocated).
But, I don't find any useful NSZombie Log in the console.
Is there a way to identify the issue ?
It's challenging. The most common cause of this error in Cocoa is directly accessing your ivars rather than using accessors. Accessors make the vast majority of memory crashes go away.
That said, they're not the only cause of memory errors. You may be accessing memory other ways. NSZombie does one specific thing: When you deallocate an object, NSZombie says "don't actually deallocate the object." Instead it turns the object into a zombie object that prints an error if you send it messages. But that only helps if the crash is due to sending a message to a deallocated instance. It could be lots of other things.
You should start first with the crash stack itself. Look up the stack and see what kind of object it might be, or who might be calling it.
Read TN2124, particularly the section on the BSD Memory Allocator, and the Enabling the Malloc Debugging Features section of the memory Usage Performance Guidelines. There are lower-level tools than NSZombie that you can use. MallocScribble is often the most useful. It overwrites deallocated memory with 0x55 so that you're more likely to crash sooner, and to make it easier to detect deallocated memory in the debugger. MallocPreScribble is useful for finding uninitialized memory, but this really only helps if you do raw malloc calls. ObjC objects are always pre-initialized.
And of course you have to put on your detective hat. What parts of your program are most suspicious? Are you doing multi-threaded work (that can cause memory crashes if you don't lock correctly).
If it reproduces easily, then you'll figure it out. If it only happens occasionally, well... I've hunted bugs like that for many months sometimes. Sometimes it's just hard.
You need to use memory profiler for that. Just build with Profile option and select Leaks.

Finding all references to an object instance in Obj-C

I'm trying to track down some bugs, and one of them is related to a memory leak. It's an object that I can tell that something still has a reference to, since Instruments still shows it as being alive, but Instruments does not register it as a leak.
Is there anyway to look at an instance of an object in Objective-C and see what other objects still have a reference to that object?
I would recommend using the Allocations/ObjectAllocations Instruments template and then in the top right corner type the class name of your object (in the Category field).
You can then see the allocations increasing as you suggest and by viewing the extended detail you can see where they were allocated.
All content below this point was added by the OP (joshbuhler)
In the screenshot below, change the filter to "Objects List", and then by clicking on the little arrow to the right of the object's address, the history of memory events (alloc/retain/release/dealloc) will be show for that object. It won't show you exactly what is hanging onto that object, but it will give you some very useful info for tracking it down.
Cautionary Tail: :)
In the process of searching for a memory leak, I set a breakpoint (really a logpoint) in Xcode that would log the value of self when it was triggered troublesome logpoint image. Meanwhile I found the leak and patched it, but the memory usage wasn't leveling out, and my de-init was never getting called. The logpoint I set earlier was actually causing the retain count of my object to increase, and in turn that prevented de-init from ever getting called. I happened to discover this after several hours of wild goose chases which culminated in me stepping through my object's methods line by line, issuing p CFGetRetainCount(self) from debug console. When I stepped over the line with the logpoint, the retain count went up. At first I assumed it was some strange side effect of my code. I moved that logpoint so that I could set a normal breakpoint on that line, and my problem moved with it. I disabled the logpoint and the leak was gone. Hopefully this can help someone else.
If you're using xCode you can use the Performance tools to find the memory leaks. That will give you a nice graph of ALL memory allocation and if they are released or leaked.
xcode -> run -> Start with Performance Tools -> Leaks.
Memory leak detection tools

Does NSLog'ing something alter its retain count? Because I am slowly going insane here

Further to this question: NSRunLoop is receiving a strange selector; possible race condition tomfoolery? - where it was discovered that a UIGestureRecognizer was being deallocated and then receiving a message, I printed out the address of one of my GRs in order to see if it was the one being reported by zombies.
With the print message in the code, I can no longer cause the crash I was originally looking for. Removing the print message, it seems I can cause it again.
Since we're dealing with a deallocation/retain/release problem, can anyone tell me if it's possible that printing out this object is causing it to be referenced, thus sparing it from deallocation? And if so, what does that tell me about my original problem? Too many release's? Release too early?
If the call to NSLog is from a background thread, then that could well be changing the sequence of events. NSLog synchronizes writes to stderr in some way -- I am not sure exactly how, but it's not far-fetched to think that one consequence could be an alteration in your object's lifetime.
As to what that tells you about the original problem, well it sounds like it confirms Dave DeLong's diagnosis: you're attempting to use a stale pointer. Which in turn means either the bit of code making the call is not retaining appropriately, or some other bit is over-releasing.
In 10 years of Mac and iOS development, it never happened to me that NSLog did something bad to reference counts. That's all I can say for sure.