原文:What Is EXC_BAD_ACCESS and How to Debug It
有時候,你會遇到由EXC_BAD_ACCESS造成崩潰。 這篇文章會告訴你什么是EXC_BAD_ACCESS,以及它產(chǎn)生的原因。我還會提供一些EXC_BAD_ACCESS錯誤的解決方案。
1. 什么是 EXC_BAD_ACCESS?
一旦你理解EXC_BAD_ACCESS的本質(zhì),你就會更好地理解其這個模糊的名詞。這里有一個極為簡單的解釋,也有一個技術層面解釋。我們首先從簡單的解釋開始說起。
2.保持簡單
不管什么時候當你遇到EXC_BAD_ACCESS這個錯誤的時候,那就意味著你向一個已經(jīng)釋放的對象發(fā)送消息。這是最常見的情況,但也有例外,我們將在稍后討論。
3. EXC_BAD_ACCESS的本質(zhì)
技術層面的解釋有些復雜。在C和Objective-C ,你是一直在處理指針。指針無非是存儲另一個變量的內(nèi)存地址的變量。當您向一個對象發(fā)送消息時,指向該對象的指針將會被引用。這意味著,你獲取了指針所指的內(nèi)存地址,并訪問該存儲區(qū)域的值。
當該存儲器區(qū)域不再映射到您的應用程序,或者換句話說,該內(nèi)存區(qū)域在你認為使用的時候卻沒有使用的時候 ,該內(nèi)存區(qū)域是無法訪問的。 這時內(nèi)核拋出一個異常( EXC ),表明你的應用程序不能訪問該存儲器塊(BAD ACCESS) 。
總之,當你碰到EXCBADACCESS ,這意味著你試圖發(fā)送消息到的內(nèi)存塊,但內(nèi)存塊無法不執(zhí)行該消息。但是,在某些情況下, EXCBADACCESS是由被損壞的指針引起的。每當你的應用程序嘗試引用損壞的指針,一個異常被內(nèi)核拋出拋出。
4.調(diào)試EXCBADACCESS
調(diào)試EXCBADACCESS可能會非常棘手和令人沮喪的。然而,現(xiàn)在EXCBADACCESS不再是你一個謎,它沒有想象中的那么可怕。 你需要知道的第一件事是您的應用程序并不一定是在崩潰的那一刻,您的應用程序不可訪問內(nèi)存區(qū)域。這就是常使調(diào)試EXCBADACCESS如此困難的原因。 同樣受損指針也是如此。您的應用程序不會崩潰,因為指針走被損壞時。同時,如果您在應用程序來回傳遞一個受損的指針也不會崩潰。當應用程序試圖引用受損指針的時候,就會發(fā)生奔潰。
5.僵尸調(diào)試模式
僵尸調(diào)試模式在過去幾年中得到了普及,事實上它們已經(jīng)出現(xiàn)在Xcode上超過十年。僵尸聽起來有點戲劇性,但它實際上是為將幫助我們調(diào)試EXCBADACCESS功能而取得一個偉大的名字。讓我來解釋它是如何工作的。
在Xcode中,您可以啟用僵尸對象,這意味著被釋放的對象將會以僵尸的形式被保留。換言之,保留釋放的對象就是為了調(diào)試。這里沒有涉及任何魔法。如果您向僵尸對象發(fā)送消息時,你的應用程序?qū)捎贓XCBADACCESS而崩潰。
這是為什么有好處嗎?讓EXCBADACCESS難以調(diào)試的原因是,你不知道你的應用程序試圖訪問哪個對象。僵尸對象在許多情況下解決這個問題。通過保留已釋放的對象,Xcode可以告訴你你試圖訪問哪個對象,這使的查找問題原因容易得多。
在Xcode中啟用僵尸是很容易的。注意,這可能會因的Xcode的版本而不同的。以下方法適用于Xcode的6和7,單擊左上角的Edit Scheme,并選中Edit Scheme。 在左側(cè)選中Run?,在上方打開?Diagnostics選項。要啟用僵尸對象,勾選?Enable Zombie Objects選框。
如果你現(xiàn)在遇到EXCBADACCESS ,在Xcode的控制臺輸出,告訴你該從哪里查找問題。看看下面的例子輸出。
2015-08-12 06:31:55.501 Debug[2371:1379247] -[ChildViewController respondsToSelector:] message sent to deallocated instance 0x17579780
在上面的例子中, Xcode告訴我們, respondsToSelector的消息:被發(fā)送到送到一個僵尸對象。然而,僵尸對象不再是ChildViewController類的一個實例。以前分配給ChildViewController實例的內(nèi)存區(qū)域不再映射到您的應用程序。這為你了解的問題產(chǎn)生的根本原因提供一個不錯的建議。
不幸的是,僵尸對象將無法保存您的一天每次崩潰的EXCBADACCESS的記錄。既然僵尸對象沒有這些伎倆,那么你可以采取其他的方法進行一些適當?shù)姆治觥?/p>
6.分析
如果僵尸對象不能解決你的問題,那么問題的根源可能就不那么簡單了。在這種情況下,您需要仔細看看在應用程序崩潰時執(zhí)行的代碼。這可能是繁瑣和耗時的。 為了幫助你發(fā)現(xiàn)你的代碼的問題,你可以使用Xcode來分析你的代碼,幫助你找到出現(xiàn)問題的地方。注意,Xcode分析項目,它會指出每一個潛在的可能出現(xiàn)的問題的地方。 使用Xcode來分析你的項目,從Xcode的?Product菜單選擇?Analyze或按?Shift-Command-B.Xcode的將需要片刻的時間,但是當它完成的時候你會在左邊的??Issue Navigator看到問題列表。由分析發(fā)現(xiàn)的問題用藍色高亮顯示。
當你點擊一個問題,Xcode的會指向問題代碼塊,這些正是你要的注意的地方。注意,Xcode僅僅是建議。在某些情況下,這是可能的,問題是不相關的,不固定。
如果你找不到造成EXCBADACCESS的錯誤,那就需要你仔細審視Xcode項目,分析其中發(fā)現(xiàn)的每一個問題。
7.結(jié)論
EXCBADACCESS是開發(fā)者面臨的一個共同的問題,它是手動內(nèi)存管理固有的問題。雖然推行ARC內(nèi)存管理方式 (自動引用計數(shù))使得EXCBADACCESS沒那么頻繁,但他們并沒有真正的消失。