开发者

NSDrawer delegate pointing to deallocated object?

A user has sent in a crash report with the stack trace listed below (I have not been able to reproduce the crash myself, but every other crash this user has reported has been a valid bug, even when I couldn't reproduce the effect). The application is a reference-counted Objective-C/Cocoa app.

If I am interpreting it correctly, the crash is caused by attempting to send a drawerDidOpen: message to a deallocated object. The only object that should be receiving drawerDidOpen: is the drawer's delegate object (nowhere does any object register to receive drawer notifications), and the drawer's delegate object is instantiated via the XIB/NIB file, wired to the delegate outlet of the drawer, and not referenced anywhere else.

Given that, how can I protect against the delegate getting dealloc'd before the drawer notification? Or, alternately, what have I misinterpreted that might be causing the crash?

Crash log/stack trace:

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x0000000000000010
Crashed Thread:  0  Dispatch queue: com.apple.main-thread

Application Specific Information:
objc_msgSend() selector name: drawerDidOpen:

Thread 0 Crashed:  Dispatch queue: com.apple.main-thread
0   libobjc.A.dylib                 0x00007fff8272011c objc_msgSend + 40
1   com.apple.Foundation            0x00007fff87d0786e _nsnote_callback + 167
2   com.apple.CoreFoundation        0x开发者_开发技巧00007fff831bcaea __CFXNotificationPost + 954
3   com.apple.CoreFoundation        0x00007fff831a9098 _CFXNotificationPostNotification + 200
4   com.apple.Foundation            0x00007fff87cfe7d8 -[NSNotificationCenter postNotificationName:object:userInfo:] + 101
5   com.apple.AppKit                0x00007fff8512e944 _NSDrawerObserverCallBack + 840
6   com.apple.CoreFoundation        0x00007fff831d40d7 __CFRunLoopDoObservers + 519
7   com.apple.CoreFoundation        0x00007fff831af8c4 CFRunLoopRunSpecific + 548
8   com.apple.HIToolbox             0x00007fff839b8ada RunCurrentEventLoopInMode + 333
9   com.apple.HIToolbox             0x00007fff839b883d ReceiveNextEventCommon + 148
10  com.apple.HIToolbox             0x00007fff839b8798 BlockUntilNextEventMatchingListInMode + 59
11  com.apple.AppKit                0x00007fff84de8a2a _DPSNextEvent + 708
12  com.apple.AppKit                0x00007fff84de8379 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 155
13  com.apple.AppKit                0x00007fff84dae05b -[NSApplication run] + 395
14  com.apple.AppKit                0x00007fff84da6d7c NSApplicationMain + 364
15  (my app's identifier)           0x0000000100001188 start + 52

edit: To clarify: This crash happened once in thousands or maybe tens of thousands of virtually-identical usage scenarios. I don't retain/release/alloc/dealloc/anything-memory-management the delegate object anywhere in my code; I don't register any object for any drawer notifications of any kind in my code; my code has no variables (nor ivars) pointing to the delegate object.

What it looks like to me is that when the NIB was unloaded (as in whatever the Cocoa system does when the document window gets closed), somehow the drawer's delegate object was dealloc'd before the drawer object itself, but the Cocoa system is supposed to prevent that from happening (and seems to handle it correctly in the vast majority of cases).


The delegate has been released to the point of deallocation without first being unregistered from the notification center (in this case, the delegation is through the notification center, not directly).

An easy fix is to call NSNotificationCenter's -removeObserver: method from your delegate's -dealloc method.


Check the backtrace -- it is through the notification center that the crash happens. Most likely, when the class is connected via setDelegate: (via the NIB file), it is done so as a notification observer.

Regardless, the relationship between notification center and your object is the same as between the object in IB and your object; weak. That is, there is no retain and, thus, your delegate is being freed too early (or, alternatively, you are over-releasing the object somewhere).

In any case, you need to make sure your delegate is retained by something somewhere for the duration of its usefulness.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜