Re: Zombie object being messaged - why?
Re: Zombie object being messaged - why?
- Subject: Re: Zombie object being messaged - why?
- From: Martin Hewitson <email@hidden>
- Date: Fri, 25 Jan 2013 19:51:41 +0100
Hi Keary,
I appreciate your response. I'll try to answer below.
>>
>> In a document based app running under ARC, I've been struggling for an eternity to get to the bottom of an occasional crash which happens when closing a document. I've spent a huge amount of time working on my -tearDown procedure which I call in my NSDocument subclass' -windowWillClose: and which subsequently calls -tearDown on many other app components. I also hit the same crash:
>>
>> [MHControlsTabBarController performSelector:withObject:]: message sent to deallocated instance 0x1075d2cb0
>
> First things first--you are getting a crash, which means that the debugger should put you exactly in the place where you can inspect the arguments being sent via this method which will likely tell you what object is sending it and potentially why.
Unfortunately, either that isn't happening, or I'm not understanding what I see. Here's an example backtrace:
[MHControlsTabBarController performSelector:withObject:]: message sent to deallocated instance 0x104bc33f0
(lldb) bt
* thread #1: tid = 0x1d07, 0x00007fff8ff5f4ce CoreFoundation`___forwarding___ + 158, stop reason = EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0)
frame #0: 0x00007fff8ff5f4ce CoreFoundation`___forwarding___ + 158
frame #1: 0x00007fff8ff5f3b8 CoreFoundation`_CF_forwarding_prep_0 + 232
frame #2: 0x00007fff93680ef7 AppKit`forwardMethod + 125
frame #3: 0x00007fff93680ef7 AppKit`forwardMethod + 125
frame #4: 0x00007fff93680ef7 AppKit`forwardMethod + 125
frame #5: 0x00007fff93680ef7 AppKit`forwardMethod + 125
frame #6: 0x00007fff93680ef7 AppKit`forwardMethod + 125
frame #7: 0x00007fff93680ef7 AppKit`forwardMethod + 125
frame #8: 0x00007fff93680ef7 AppKit`forwardMethod + 125
frame #9: 0x00007fff93680ef7 AppKit`forwardMethod + 125
frame #10: 0x00007fff93680ef7 AppKit`forwardMethod + 125
frame #11: 0x00007fff93648a83 AppKit`-[NSWindow sendEvent:] + 7994
frame #12: 0x00007fff9364442c AppKit`-[NSApplication sendEvent:] + 4969
frame #13: 0x00007fff9355a2fa AppKit`-[NSApplication run] + 636
frame #14: 0x00007fff934fecb6 AppKit`NSApplicationMain + 869
frame #15: 0x0000000100001d02 TeXnicle`main + 34 at main.m:32
frame #16: 0x0000000100001cd4 TeXnicle`start + 52
Here's another example:
[MHControlsTabBarController performSelector:withObject:]: message sent to deallocated instance 0x127ef9fd0
(lldb) bt
* thread #1: tid = 0x1d07, 0x00007fff8ff5f4ce CoreFoundation`___forwarding___ + 158, stop reason = EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0)
frame #0: 0x00007fff8ff5f4ce CoreFoundation`___forwarding___ + 158
frame #1: 0x00007fff8ff5f3b8 CoreFoundation`_CF_forwarding_prep_0 + 232
frame #2: 0x00007fff93680ef7 AppKit`forwardMethod + 125
frame #3: 0x00007fff93648a83 AppKit`-[NSWindow sendEvent:] + 7994
frame #4: 0x00007fff9364442c AppKit`-[NSApplication sendEvent:] + 4969
frame #5: 0x00007fff9355a2fa AppKit`-[NSApplication run] + 636
frame #6: 0x00007fff934fecb6 AppKit`NSApplicationMain + 869
frame #7: 0x0000000100002022 TeXnicle`main + 34 at main.m:32
frame #8: 0x0000000100001ff4 TeXnicle`start + 52
> Without this knowledge, everything you do is just random stabs and may not solve the problem even if it seems to go away.
That's exactly how I feel. I just keep trying things, but nothing seems very systematic. Most unsatisfying.
>
> Just a quick suggestion--have you searched your code to see if you ever call this method?
No, I never message MHControlsTabBarController with performSelector:...
>
>> MHControlsTabBarController is a view controller whose view is added to the document's main window when the document loads.
>>
>> In my document's -tearDown I do:
>>
>> // clean up tab bar controls
>> [self.controlsTabBarController tearDown];
>> self.controlsTabBarController = nil;
>>
>> In [MHControlsTabBarController tearDown] I nil out various state variables. I've also tried various things in that -tearDown, like removing the view controller's view from the superview, cancelling any run loop performs by doing:
>>
>> [[NSRunLoop currentRunLoop] cancelPerformSelectorsWithTarget:self];
>> [[NSRunLoop mainRunLoop] cancelPerformSelectorsWithTarget:self];
>
> IIRC performSelector:withObject: is not a run loop action--it is immediate dispatch, so doing the above is one of those useless stabs I mentioned.
Ah, good to know. So I don't need to do that.
>
>> nilling out all IBOutlets, etc, but nothing helps so far.
>
>> Should I interpret this as a window trying to message the object? Am I somehow over-reasling? Under ARC, I can't, right? If it's not coming from a window, how can I figure out which object is trying to message this deallocated MHControlsTabBarController?
>
> If you are using ARC, I don't think you should be doing any explicit memory management except to explicitly balance other explicit memory management calls; and if you aren't, then you aren't over-releasing. Minimally, some object has a weak reference to your MHControlsTabBarController, and that can happen, so once you know who and why you can prevent it.
I do lots of nilling of unsafe_unretained IBOutlet connections. I think that's correct, isn't it? I also do things like nilling delegates, and releasing ivar objects (arrays etc).
>
>> There are a number of timer-based activities which check the state of this controls controller but in the document's -tearDown I try to stop all timers. The problem is, how can I ensure that all timers (and any actions already triggered) have stopped, before I go ahead tearing down everything else? I sort of need to delay the document closing somehow, but I asked about this in an earlier thread (this has been a loooong story) and was advised (probably rightly) that this was bad design. But this seems like a general problem to me, for which there is surely a general pattern which solves it. If I have timer-based activities, how do I make sure they are stopped before the rug is pulled from under their feet?
>
> Whichever object set up the timers should invalidate them before their target would be released, so the validity of the target should be known and deterministic to that object. Sometimes easier said than done, but there it is. In any case it is not likely that a timer is responsible since they are supposed to retain or maintain a strong reference to their target until they are invalidated, after which time they would not fire anyway.
Hmm, that all sounds good, but I thought I'd come up with a scenario in my head where the timer could fire, the selector is called, the selector then calls out to other objects (a delegate, for example), which may no longer exit. But I'm always checking if self.delegate==nil before doing this, so I guess that can't be the issue. I need to think about that some more.
Thanks!
Martin
>
> HTH,
>
> Keary Suska
> Esoteritech, Inc.
> "Demystifying technology for your home or business"
>
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden