How to debug "message sent to deallocated instance" in Xcode 4?
I pressed alt+cmd+r and activated NSZombieEnabled in Arguments > Environment Variables. Additionally, I activated it in Diagnostics > Memory Management > Enable Zombie Objects.
However, when I built and run, at some point my app crashes giving me this useless message in the console:
*** -[CALayer retainCount]: message sent to deallocated instance 0x656b260
The stack trace is just as useless. I moved the details-level slider all the way to the right. Thread 1 simply shows me this:
Everything is system-owned and there's not a single line related to my app. So obviously NSZombiesEnabled doesn't work as it did in Xcode 3, where it halted on the dead object.
Is there any way to figure out which CALayer is deallocated too early?
Update: So after building and running about 100 more times suddenly the problem DISAPPEARED! It's completely gone! And the best part: I did not modify my code in any way! Inbetween I cleaned the build folder and project with the clean commands several times and deleted the app in the Simulator several times as well.
Update 2: Fortunately the problem re-appeared. And now it seems persistent. Fortunately, because I prefer finding the root cause rather than annoying the users by random.
Update 3: Finally found it by accident:
startButton = newBttn;
should have been:
self.startButton = newBttn;
startButton was a retaining property and in -dealloc I released it. So it got overreleased and in most (but not all) cases after the view faded out it crashed giving that weird CALayer retainCount message.
The Zombies Instrument (CMD + I) finally pointed out that it had to do with a button. Just didn't know why and where.
Clang Static Analyzer didn't complain about this obvious glitch.
If this crops up again, you can run a dedicated Zombies instrument. Hit Command+I to profile the app and select the Zombies instrument (you must be running on the simulator). If you get a zombie, you can display the entire memory history (each retain/release) for that object, which is immensely helpful in tracking down errors.
In addition to Jeff's great answer; to do almost the same thing, but without having to open Instruments or profile your App, you can set NSZombieEnabled, MallocStackLogging, and guard malloc in the debugger. Then, when your App crashes, type this in the gdb console:
(gdb) info malloc-history 0x543216
Replace 0x543216
with the address of the object that caused the crash, and you will get a much more useful stack trace and it should help you pinpoint the exact line in your code that is causing the problem.
This article has some additional info.