I've got a retain/release problem. My View is pretty complicated so I've set NSZombieEnabled to YES and am trying to locate which, exactly, object is causing me grief. To speed this process along I'm wondering if there hints or tricks to tracking the Zombies back to the grave they dug their way out of (sorry, had to) or, back to the object they're associated with? The cryptic console message doesn't appear to offer much insight:
NSInvocation: warning: object 0x1076850 of class '_NSZombie_CALayer' does not implement methodSignatureForSelector: -- trouble ahead
I have no selectors called "trouble ahead".
Edit - Including Stack Trace:
#0 0x3026e017 in ___forwarding___
#1 0x3024a0a2 in __forwarding_prep_0___
#2 0x302042e8 in CFRelease
#3 0x00c4fc31 in CALayerUpdateSublayers
#4 0x00c4e173 in -[CALayer dealloc]
#5 0x00c4000e in CALayerRelease
#6 0x00c48dad in CALayerFreeTransaction
#7 0x00c410b8 in CA::Transaction::commit
#8 0x00c492e0 in CA::Transaction::observer_callback
#9 0x30245c32 in __CFRunLoopDoObservers
#10 0x3024503f in CFRunLoopRunSpecific
#11 0x30244628 in CFRunLoopRunInMode
#12 0x32044c31 in GSEventRunModal
#13 0x32044cf6 in GSEventRun
#14 0x309021ee in UIApplicationMain
#15 0x00001eb4 in main at main.m:14
Edit 2: ObjectAlloc
Looking up the memory address in question in ObjectAlloc I find two matches:
# Address Category Creation Time Size Responsible Library Responsible Caller
0 0x1076980 GeneralBlock-48 00:11.470 48 QuartzCore -[CALayer setDelegate:]
1 0x1076980 CALayer 00:11.552 48 UIKit -[UIView _createLayerWithFrame:]
Digging into #0 GeneralBlock-48:
# Category Event Type Timestamp Address Size Responsible Library Responsible Caller
0 GeneralBlock-48 Malloc 00:11.470 0x1076980 48 QuartzCore -[CALayer setDelegate:]
1 GeneralBlock-48 Free 00:11.551 0x1076980 -48 QuartzCore -[CALayer addAnimation:forKey:]
2 CALayer Malloc 00:11.552 0x1076980 48 UIKit -[UIView _createLayerWithFrame:]
Digging into #1 CALayer:
# Category Event Type Timestamp Address Size Responsible Library Responsible Caller
0 GeneralBlock-48 Malloc 00:11.470 0x1076980 48 QuartzCore -[CALayer setDelegate:]
1 GeneralBlock-48 Free 00:11.551 0x1076980 -48 QuartzCore -[CALayer addAnimation:forKey:]
2 CALayer Malloc 00:11.552 0x1076980 48 UIKit -[UIView _createLayerWithFrame:]
Well, I see now that drilling deeper in either #0 or #1 reveals the exact same information. I suppose that should cut troubleshooting this in half...but I'm still at a loss...
I believe the backtrace is just the point where the zombie is being messaged. This backtrace usually gives you zero information about what is causing the crash. It pretty much only tells you the type and the address of the object that is being over-released.
A technique I often use to track down over-releases like this is to use Instruments' ObjectAlloc to track all retains and releases. Find the address for the over-released object in ObjectAlloc, then list all the retain/release calls, and then try to balance each retain with a release. Once you find a release without a retain to match, You've found the problem.
One quick thing you can do is set a symbolic breakpoint on objc_exception_throw
. This will cause your program to pause whenever an exception is thrown. This may not help you track down exactly which CALayer
is giving you grief, but it should help you find the general vicinity where it's being called.
“trouble ahead” is part of the warning, not the selector. The warning itself comes from NSInvocation, but the fact that it mentions “class _NSZombie_CALayer” means that something’s trying to work with a CALayer that’s been dealloced.
The stack trace indicates that this is happening when a layer is trying to release its sublayers.
Altogether, this means that the layer being released has a sublayer that has been over-released somewhere in your code. Check your memory management of CALayers, or try the Clang Static Analyzer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With