2010-05-31 85 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