2010-05-31 86 views
0

用户使用下面列出的堆栈跟踪发送了崩溃报告(我无法自己重现崩溃,但是此用户报告的每次其他崩溃都是有效的错误,即使我无法重现影响)。该应用程序是一个引用计数的Objective-C/Cocoa应用程序。指向释放对象的NSDrawer委托?

如果我正确解释它,崩溃是由试图发送一个drawerDidOpen:消息到释放对象引起的。应该接收的唯一对象是抽屉的委托对象(不通过任何对象寄存器来接收抽屉通知),并且抽屉的委托对象通过连接到抽屉的委托出口的XIB/NIB文件实例化,而不是参考其他地方。

鉴于这一点,我该如何防止委托人在抽屉通知之前取消分配?或者,或者,我误解了可能导致崩溃的原因?

崩溃日志/堆栈跟踪:

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  0x00007fff831bcaea __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 

编辑:为了澄清:这个崩溃千发生了,也许成千上万的几乎完全相同的使用场景一次或。我不保留/释放/分配/ dealloc /任何内存管理委托对象在我的代码中的任何地方;我不会在我的代码中注册任何类型的任何抽屉通知的对象;我的代码没有指向委托对象的变量(也不是ivars)。

对我来说,当NIB被卸载时(就像Cocoa系统在文档窗口关闭时所做的那样),不知何故抽屉的委托对象在抽屉对象本身之前被解除分配,但是可可系统应该阻止这种情况的发生(并且似乎在绝大多数情况下都能正确处理)。

+0

您看到'KERN_INVALID_ADDRESS at 0x0000000000000010'?这很可能意味着你的程序认为代表在那里。最明显的是,情况并非如此。 – zneak 2010-05-31 18:53:15

+0

对,很清楚。问题是*为什么*不是那里的代表? – Isaac 2010-05-31 19:56:35

回答

1

代理已经释放到释放位置,而没有首先从通知中心注销(在这种情况下,代表团通过通知中心,而不是直接)。

一个简单的解决办法是从您的代理人的-dealloc方法中调用NSNotificationCenter's-removeObserver:方法。


检查回溯 - 通过通知中心发生事故。当班级通过setDelegate:(通过NIB文件)连接时,很可能是通知观察员完成的。

无论如何,通知中心与您的对象之间的关系与IB中的对象与您的对象之间的关系相同;弱。也就是说,没有retain,因此,您的代理被释放得太早(或者,您在某处过度释放该对象)。

在任何情况下,您都需要确保您的委托在某个地方保留了一段时间,以保证其有用性。

+0

如果委托人通过NSNotificationCenter注册自己,我会理解的(事实上,我曾两次检查过任何NSNotificationCenter注册抽屉通知的实例),但委托仅在NIB中实例化,并且只由委托' 'NSDrawer'上的IBOutlet' - 也就是说,通过'[theDrawerObjectOfSomeWindow delegate]'获得指向我代码中委托对象的唯一方法。 – Isaac 2010-05-31 23:31:19

+0

关于回溯/通知中心,是的,它正在通过通知中心,但由于我没有要求观察,我不应该删除观察者(即,如果注册对我隐藏,注销应该隐藏也是)。 根据每个http://developer.apple.com/mac/library/documentation/cocoa/conceptual/LoadingResources/CocoaNibs/CocoaNibs.html#//apple_ref/doc/uid/10000051i-CH4-SW6实例化的顶级对象NIB在引用计数环境中的保留计数为1,所以我不明白为什么/代表对象如何获取dealloc'd。 – Isaac 2010-06-01 04:50:10

+0

奇怪的是,虽然引用的文档说我应该释放在NIB中实例化的顶层对象,但“构建和分析”会将该版本标记为缺陷。 – Isaac 2010-06-01 04:53:18