52

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:

screenshot

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.

Iulian Onofrei
  • 9,188
  • 10
  • 67
  • 113
dontWatchMyProfile
  • 45,440
  • 50
  • 177
  • 260
  • 1
    No bug just "fixes itself". This is most likely a concurrency related ownership issue and quite likely still exists in your code. A ticking time bomb, if you will. In your shoes, I'd take a very hard look at how I'm managing any Core Animation based resources... – bbum Nov 28 '11 at 19:31
  • What exactly do you mean by Core Animation based resources? – dontWatchMyProfile Nov 28 '11 at 22:43
  • Anything related to laying gunk out on the screen. If you are suing cocos2d, you'd need to review your management of resources therein as it indirectly manages CA* resources. – bbum Nov 29 '11 at 06:09

2 Answers2

102

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.

Jeff Kelley
  • 19,021
  • 6
  • 70
  • 80
  • Great tool! Thanks! Although it shows a better stack trace now, I can't figure out which UIView owns that CALayer zombie. Can you point out a good resource which shows how to use that instrument in a case like this? – dontWatchMyProfile Nov 28 '11 at 22:08
  • 2
    This just made my day. I had no idea you could profile an app like that. You have no idea how happy I am right now. – shulmey May 21 '13 at 23:08
  • Working For me on device too :-) Thank You – Yogesh Patel Jan 28 '19 at 05:33
  • 2
    Needs more detail on "If you get a zombie, you can...". I launched my app under Instruments, chose Zombies, hit the Record button which launched my app, followed the necessary steps to cause the zombie crash, my app ceased to run at that point (icon disappeared from Dock), and Instruments stopped recording but displayed no error message. Eventually I discovered the little purple flag, clicked on that, and followed the arrow to a history. Clicking "Unpaired" proved helpful for narrowing down to the key events. – bhaller Jun 30 '21 at 17:40
58

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.

Iulian Onofrei
  • 9,188
  • 10
  • 67
  • 113
chown
  • 51,908
  • 16
  • 134
  • 170
  • I think that the Zombies tool is basically a GUI wrapper around this exact procedure -- it just handles some of the grunt work for you. – Olie Apr 10 '13 at 23:53
  • 33
    FYI: With the LLDB debugger you can do this as follows: (lldb) script import lldb.macosx.heap (lldb) malloc_info --stack-history 0x7c506a00 – Ron Feb 20 '15 at 14:29
  • 23
    The LLDB command to load the script is actually `command script import lldb.macosx.heap` (note first word). This will respond with something like `"malloc_info", "ptr_refs", "cstr_refs", and "objc_refs" commands have been installed, use the "--help" options on these commands for detailed help.` if it worked correctly – Perry Apr 21 '15 at 15:16