用户已使用下面列出的堆栈跟踪发送崩溃报告(我自己无法重现崩溃,但此用户报告的每次其他崩溃都是有效的错误,即使我无法重现效果)。该应用程序是一个引用计数的Objective-C / Cocoa应用程序。
如果我正确解释它,则会因尝试向已释放的对象发送drawerDidOpen:
消息而导致崩溃。应该接收drawerDidOpen:
的唯一对象是抽屉的委托对象(没有任何对象注册接收抽屉通知),抽屉的委托对象通过XIB / NIB文件实例化,连接到委托出口抽屉,并没有在其他地方引用。
鉴于此,我如何防止代理人在抽屉通知之前获得dealloc'd?或者,或者,我误解了可能导致崩溃的原因是什么?
崩溃日志/堆栈跟踪:
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
编辑:澄清一下:这次崩溃发生在数千甚至数万个几乎相同的使用场景中。我没有在代码中的任何地方保留/ release / alloc / dealloc / anything-memory-management委托对象;我没有为我的代码中的任何抽屉通知注册任何对象;我的代码没有指向委托对象的变量(也没有ivars)。
对我而言,当NIB被卸载时(就像Cocoa系统在文档窗口关闭时所做的那样),抽屉的委托对象在抽屉对象本身之前被解除了,但是Cocoa系统应该防止这种情况发生(并且似乎在绝大多数情况下都能正确处理它)。
答案 0 :(得分:1)
该代表已被释放到释放点,而没有首先从通知中心取消注册(在这种情况下,代表团是通过通知中心,而不是直接)。
一个简单的解决方法是从您委托的NSNotificationCenter's
方法中调用-removeObserver:
-dealloc
方法。
检查回溯 - 通过通知中心发生崩溃。最有可能的是,当通过setDelegate:
(通过NIB文件)连接类时,它是作为通知观察者完成的。
无论如何,通知中心和您的对象之间的关系与IB中的对象和您的对象之间的关系相同;弱。也就是说,没有retain
因此,你的委托被过早释放(或者,你在某处过度释放了对象)。
在任何情况下,您都需要确保您的委托在其有效期内由某个地方保留。