Objective-C release of zombie object after storyboard modification

732 Views Asked by At

I have some crushes in iOS application. After investigation I found that problem is some dangling pointer. To find where where it came from I've started profiling code on simulator (iOS 6.1) using "Zombies" trace template.

Test scenario is quite simple: select some item on table, then move to next controller by invoking proper sway by its name, then press back button. Crush appears when "back" animation is finished.

Here is table form profiler with data for released zombie object (I removed uninteresting columns like: #; Category - always equal CALayer; timestamp):

Event Type  RefCt   Size    Responsible Library Responsible Caller
Malloc      1       48      UIKit               -[UIView _createLayerWithFrame:]
Retain      3       0       QuartzCore          CA::Layer::insert_sublayer(CA::Transaction*, CALayer*, unsigned long)
Release     2       0       UIKit               -[UIView(Internal) _addSubview:positioned:relativeTo:]
Retain      3       0       QuartzCore          -[CALayerArray mutableCopyWithZone:]
Release     2       0       UIKit               -[UIView(Hierarchy) bringSubviewToFront:]
Retain      3       0       QuartzCore          -[CALayerArray copyWithZone:]
Release     2       0       UIKit               -[UIView(Hierarchy) _makeSubtreePerformSelector:withObject:withObject:copySublayers:]
Retain      3       0       QuartzCore          -[CALayerArray copyWithZone:]
Release     2       0       UIKit               -[UIView(Internal) _didMoveFromWindow:toWindow:]
Retain      2       0       QuartzCore          -[CALayerArray copyWithZone:]
Release     1       0       UIKit               -[UIView(Hierarchy) _makeSubtreePerformSelector:withObject:withObject:copySublayers:]
Retain      3       0       QuartzCore          -[CALayerArray copyWithZone:]
Release     2       0       UIKit               -[UIView(Internal) _didMoveFromWindow:toWindow:]
Retain      3       0       QuartzCore          -[CALayerArray copyWithZone:]
Release     2       0       UIKit               -[UIView dealloc]
Release     1       0       UIKit               -[UIView dealloc]
Zombie      -1      0       QuartzCore          CA::release_objects(X::List<void const*>*)

Now this table doesn't point anywhere to my code, all entries are related to system libraries: UIKit or QuartzCore. So I can't show my code, since I have no idea which part is wrong and there is a lot of it.

When I've try review change history, the only significant changes in first commit with this problem, are those made in storyboard. This is strange since changes in storyboard should not have such problems. I can't say what exactly was changed (storyboard XML is very hard to read).

Any proposal how can I locate/fix this issue? Or maybe someone had similar problem?

2

There are 2 best solutions below

3
Jeffery Thomas On

I am very suspicious of:

Release     2       0       UIKit               -[UIView dealloc]
Release     1       0       UIKit               -[UIView dealloc]

What are the call stacks for these calls?

In the past, I've had issues caused by improperly releasing properties in -dealloc. Just to be sure, I seal pointers after releasing them in -dealloc.

[_prop release]; _prop = nil;
0
Marek R On

Finally I have found the problem.

Problem was caused by incorrect merge and for some IBOutlet property release method was called twice on controllers deallocation. Those calls were separated by other release calls for other properties so it was easy to miss. Problem is in production code but didn't appeared earlier since it was in root view controller (so it lived as long as application). (I've inherited such "wonderful" code)

Now I have new UI spec and change order of controllers and problematic controller is no longer first in the view controllers stack, so it is getting deallocated and bug started to manifest it self.

I've wasted two work days to find this :).

Thanks you to: "Jeffery Thomas" and "Bernd Rabe", your feed back let me find the problem.

Funny that XCode tool: "Product/Analyze" didn't detect this. Definitely it should.
Also Profiler when tracking zombies should complain about object which is root of problem, now it complains about child of problematic object. Simply zombie exception should be risen before dealloc was called not after.