Turns out, I’ve written some serious nonsense
If zombies worked like I originally wrote, turning on zombies would directly lead to innumerable false positives…
There is some isa-swizzling going on, probably in _objc_rootRelease
, so any override of dealloc
should still be called with zombies enabled. The only thing that won’t happen with zombies is the actual call to object_dispose
— at least not by default.
What’s funny is that, if you do a little logging, you will actually see that even with ARC enabled, your implementation of dealloc
will call through to it’s superclass’s implementation.
I was actually assuming to not see this at all: since ARC generates these funky .cxx_destruct
methods to dispose of any __strong
ivars of a class, I was expecting to see this method call dealloc
— if it’s implemented.
Apparently, setting NSZombieEnabled
to YES
causes .cxx_destruct
to not be called at all — at least that’s what happened when I’ve edited your sample project:
zombies off leads to backtrace and both deallocs, while zombies on yields no backtrace and only one dealloc.
If you’re interested, the additional logging is contained in a fork of the sample project — works by just running: there are two shared schemes for zombies on/off.
Original (nonsensical) answer:
This is not a bug, but a feature.
And it has nothing to do with ARC.
NSZombieEnabled
basically swizzles dealloc
for an implementation which, in turn, isa-swizzles that object’s type to _NSZombie
— a dummy class that blows up, as soon as you send any message to it. This is expected behavior and — if I’m not entirely mistaken — documented.