Re: NSTableView is messaging zombie delegate
Re: NSTableView is messaging zombie delegate
- Subject: Re: NSTableView is messaging zombie delegate
- From: corbin dunn <email@hidden>
- Date: Tue, 10 May 2016 08:03:06 -0700
> On May 6, 2016, at 1:03 PM, Matthew LeRoy <email@hidden> wrote:
>
> Hello,
>
> I'm having an issue where an NSTableView appears to be messaging its delegate after the delegate has been deallocated, causing an EXC_BAD_ACCESS crash. It doesn't always happen, but it happens regularly. My understanding is that NSTableView's delegate is a zeroing weak reference, and so I'm stumped as to how/why it is sending a message to the delegate after the delegate has been deallocated.
Where does it say that? It is not a zero’ing weak reference.
corbin
>
> The basic scenario is that my application shows a custom modal sheet which contains an NSTableView. The NSWindow for the sheet is loaded from a Nib via an NSWindowController, and contains (among other things) an empty NSView which is a placeholder for additional UI. An NSViewController loads the additional UI (which includes the NSTableView) from a separate Nib and the UI is placed in the placeholder NSView within the NSWindow. The application holds a reference to the NSWindowController, which holds a reference to the NSViewController, which has a *weak* reference (outlet) to the NSTableView. The NSTableView's delegate is its File's Owner (the NSViewController).
>
> The crash can be made to happen simply by showing the sheet ([NSApp beginSheet:...]), then immediately closing it ([NSApp endSheet:returnCode:], followed by [sheet orderOut:self], [sheet close], _windowController = nil;). Again, it doesn't happen every time, but when it does it appears that the NSTableView sends -respondsToSelector: to its delegate, even though the delegate (the NSViewController) has been deallocated. Here's the stack trace from the crash log:
>
> Application Specific Information:
> objc_msgSend() selector name: respondsToSelector:
>
> Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
> 0 libobjc.A.dylib 0x00007fff9267d4dd objc_msgSend + 29
> 1 com.apple.AppKit 0x00007fff975fa76d -[NSTableRowData _removeViewAndAddToReuse:forRow:] + 163
> 2 com.apple.CoreFoundation 0x00007fff98e11496 __65-[__NSDictionaryM enumerateKeysAndObjectsWithOptions:usingBlock:]_block_invoke + 102
> 3 com.apple.CoreFoundation 0x00007fff98e11389 -[__NSDictionaryM enumerateKeysAndObjectsWithOptions:usingBlock:] + 185
> 4 com.apple.AppKit 0x00007fff9779941c -[NSTableRowData _removeNonVisibleViewsInDictionary:] + 88
> 5 com.apple.AppKit 0x00007fff9753900c -[NSTableRowData _removeRowsBeingAnimatedOff] + 60
> 6 com.apple.Foundation 0x00007fff84a09b4e __NSFireDelayedPerform + 377
> 7 com.apple.CoreFoundation 0x00007fff98e1cb94 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 20
> 8 com.apple.CoreFoundation 0x00007fff98e1c823 __CFRunLoopDoTimer + 1075
> 9 com.apple.CoreFoundation 0x00007fff98e1c37a __CFRunLoopDoTimers + 298
> 10 com.apple.CoreFoundation 0x00007fff98e13871 __CFRunLoopRun + 1841
> 11 com.apple.CoreFoundation 0x00007fff98e12ed8 CFRunLoopRunSpecific + 296
> 12 com.apple.HIToolbox 0x00007fff882f7935 RunCurrentEventLoopInMode + 235
> 13 com.apple.HIToolbox 0x00007fff882f7677 ReceiveNextEventCommon + 184
> 14 com.apple.HIToolbox 0x00007fff882f75af _BlockUntilNextEventMatchingListInModeWithFilter + 71
> 15 com.apple.AppKit 0x00007fff97431df6 _DPSNextEvent + 1067
> 16 com.apple.AppKit 0x00007fff97431226 -[NSApplication _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 454
> 17 com.apple.AppKit 0x00007fff97425d80 -[NSApplication run] + 682
> 18 com.apple.AppKit 0x00007fff973ef368 NSApplicationMain + 1176
> 19 libdyld.dylib 0x00007fff984505ad start + 1
>
> I've reproduced the crash using the Zombies template in Instruments, and it indicates that the NSViewController is indeed the zombie object that is being sent the -respondsToSelector: message.
>
> I've pored over the retain/release log in Instruments for the NSViewController instance and everything appears to be in order - in order words, I don't think I'm over-releasing it. Based on my debugging, the NSTableView appears to be living on well after the NSWindowController has been released and deallocated (which causes the NSViewController to also be released and deallocated). I would've expected that the NSTableView would be deallocated before the NSViewController or NSWindowController since I'm not holding any references to it elsewhere, but it appears it isn't deallocated until later (I have confirmed that it is in fact being deallocated eventually). Still, even if the NSTableView outlives its delegate, shouldn't the delegate reference get zeroed when the delegate gets deallocated? Why isn't it in this case?
>
> Notably, this code hasn't changed and has been in the field for at least 6 months, and we only first started seeing the crash when testing on 10.11.4. It also happens regularly on the latest 10.11.5 beta. We initially thought it was limited to those as we weren't able to reproduce it on earlier OS X versions, but we've since reproduced it at least once as early as 10.9 (not sure which point release). However, it is definitely happening more frequently/regularly on 10.11.4 and .5.
>
> At this point I'm at a loss for how to track this any further. Any help would be greatly appreciated!
>
> Matt
> _______________________________________________
>
> 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
_______________________________________________
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