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.

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 (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to