2010-01-29 109 views
0

我被一個我無法弄清楚如何調試的bug所困擾。基本上我在模擬器上運行我的代碼,一切都很好。手機上的Debuggin iPhone應用程序

但是,當我轉到實際設備時,出現EXC_BAD_ACCESS錯誤。不幸的是,當在調試器下的手機上運行時,該死的事情工作得很好,所以我無法判斷錯誤發生的位置。

我確實得到了一個我無法重現的堆棧跟蹤,所以我很確定我的代碼中導致問題的那行是這一行(但我不能爲我的生活弄清楚這怎麼可能):是

[[NSNotificationCenter defaultCenter] postNotificationName:@"SubscriberChanged" object: nil]; 

實際的錯誤上objc_msgSend這一行約四幀以下,但其似乎是在iPhone SDK的一部分代碼,所以我沒有源檢查它。

任何人都可以給我幾個關於如何去找出這個問題的方法嗎?我有一個最後期限運送這個東西,我不能讓它像這樣出去......

我終於成功地在調試器中重現了這一點。我得到的堆棧跟蹤如下:


#0 0x30011940 in objc_msgSend() 
#1 0x3054dc80 in _nsnote_callback() 
#2 0x3024ea58 in _CFXNotificationPostNotification() 
#3 0x3054b85a in -[NSNotificationCenter postNotificationName:object:userInfo:]() 
#4 0x3054dbc0 in -[NSNotificationCenter postNotificationName:object:]() 
#5 0x000027c6 in -[My2CentsAppDelegate handleMOCChange:] (self=0x1159d0, _cmd=0x2bf90, notification=0x147400) at /Users/sdussin/Desktop/UPOD Research LLC/Development/My2Cents/Classes/My2CentsAppDelegate.m:52 
#6 0x3054dc80 in _nsnote_callback() 
#7 0x3024ea58 in _CFXNotificationPostNotification() 
#8 0x3054b85a in -[NSNotificationCenter postNotificationName:object:userInfo:]() 

堆棧跟蹤中的幀#5對應於上面的行。

回答

2

如果不能重複你的崩潰在調試器,你可以嘗試其他的方法來解決它:

  • 審查代碼(也許問朋友或同事的代碼審查)
  • 添加logging和斷言
  • 激活所有(或至少大多數)的編譯器警告,並服從他們
  • 請務必使用[]鐺2靜態分析和聽從警告

尤其是clang很擅長查找內存管理錯誤。 EXC_BAD_ACCESS就像一個味道。

可能是您註冊的觀察員之一NSNotificationCenter已發佈。請記住,

重要:通知中心 不保留其觀察員, 因此,你必須確保你 註銷觀察員(使用 removeObserver:或 removeObserver:名稱:對象:) 才被釋放。 (如果你不這樣做, 你會如果 中心將消息發送到一個釋放 對象生成運行時錯誤。)

+0

原來的通知是問題。我顯然在我的NIB中有幾個視圖對象的實例。當他們得到加載時,他們每個都註冊通知,然後只保留其中的一個。其他人被釋放,但未能取消通知。 感謝所有... – Steve 2010-02-01 20:09:51

-1

通常,當你得到一些地方在模擬器上運行,但沒有設備的情況下,反之亦然,原因是沒有爲處理器崩潰而編譯的庫/框架。

在你的情況,你會有一個ARM庫/框架,在設備上正常工作,但在i386上運行的模擬器上崩潰。我會檢查爲該通知註冊的任何對象的繼承。

2

你可以使用NSZombieEnabled(谷歌它)來跟蹤這類事情。除此之外,我第二個問題是:您可能需要取消某個觀察者的註冊,例如,一個已經卸載但仍然作爲觀察者註冊的視圖控制器。

+0

非常好的建議 - 確保把 如果(GETENV( 「NSZombieEnabled」)|| GETENV( 「NSAutoreleaseFreedObjectCheckEnabled」)) \t \t的NSLog(@ 「啓用NSZombieEnabled/NSAutoreleaseFreedObjectCheckEnabled!」); 在你的AppDelegate.m中警告你,如果你不需要時忘記關閉它。 – 2010-01-30 03:56:23

+0

抱歉格式化,在評論框中沒有代碼標籤。 – 2010-01-30 03:57:39

+0

我對此有一個問題:如果我在手機上運行而不使用調試器,我該如何看到NSZombieEnabled的輸出?當我在調試器下運行殭屍時,我的印象是殭屍已經登錄到控制檯,但他們在哪裏打電話? – Steve 2010-02-02 13:25:43

1

發生崩潰的原因是某些對象已註冊您要發送的通知,並且在發佈之前未取消訂閱。所以當你發送通知時,它會嘗試回覆那個對象,然後繁榮。

查看代碼中您訂閱的所有位置,並查看您錯過取消訂閱的位置(例如,您是否在dealloc中取消訂閱?)。

同樣如上所述,NSZombieEnabled = YES,通過右鍵單擊XCode項目瀏覽器中的可執行文件並轉到參數選項卡並將其添加到環境變量中來設置環境標誌。然後看日誌,當你發送通知時,你會看到一條消息,如「發送給釋放實例的消息等等」。

1

粘性軌跡告訴你註冊「SubscriberChanged」通知的對象已被釋放。處理這個問題最簡單的方法是尋找所有註冊了「SubscriberChanged」通知的類,並讓它們在[dealloc]方法中註銷。

相關問題