- 簡(jiǎn)單的理解:當(dāng)遇到了EXC_BAD_ACCESS異常,意味著訪問(wèn)了一個(gè)已經(jīng)被釋放的內(nèi)存區(qū)域。
- 指針層面理解:從C、OC語(yǔ)言來(lái)解釋,我們平時(shí)所操作的對(duì)象其實(shí)是一個(gè)指針,指針是指向另一塊存儲(chǔ)區(qū)域的變量。當(dāng)向一個(gè)對(duì)象發(fā)送消息,指向這個(gè)對(duì)象的指針需要被使用,也就是你獲得了指針指向的內(nèi)存地址并且可以訪問(wèn)該內(nèi)存塊的值。當(dāng)系統(tǒng)不再為你映射該內(nèi)存塊時(shí),換句話說(shuō),該內(nèi)存塊已經(jīng)不能夠被你所使用,則不可以再次訪問(wèn)該內(nèi)存塊。 如果再次訪問(wèn)這塊內(nèi)存,發(fā)生這種情況時(shí),內(nèi)核會(huì)發(fā)送一個(gè)異常(EXC),表明您的應(yīng)用程序無(wú)法訪問(wèn)該內(nèi)存塊(BAD ACCESS)。
總之,當(dāng)遇到了EXC_BAD_ACCESS異常,意味你嘗試向一個(gè)塊已經(jīng)不能執(zhí)行這個(gè)消息的內(nèi)存塊發(fā)送消息。
在某些情況下,訪問(wèn)野指針也會(huì)導(dǎo)致EXC_BAD_ACCESS。當(dāng)應(yīng)用程序嘗試去使用一個(gè)野指針的時(shí)候,EXC_BAD_ACCESS就會(huì)被內(nèi)核拋出。
調(diào)試EXC_BAD_ACCESS
因?yàn)楫?dāng)內(nèi)存塊不能被應(yīng)用程序所使用的時(shí)候,并不會(huì)立即出現(xiàn)crash,所以導(dǎo)致調(diào)試EXC_BAD_ACCESS很麻煩。
對(duì)于野指針也是同樣的,應(yīng)用程序不會(huì)立即崩潰如果存在野指針,只有當(dāng)應(yīng)用程序試圖去使用野指針的時(shí)候才會(huì)崩潰。
僵死對(duì)象
僵尸對(duì)象聽起來(lái)有點(diǎn)奇怪,但確實(shí)是可以用來(lái)幫助調(diào)試EXC_BAD_ACCESS問(wèn)題。非常有效!
Xcode中,可以開啟僵尸對(duì)象模式。

之所有調(diào)試EXC_BAD_ACCESS非常麻煩是因?yàn)椴恢缿?yīng)用程序要訪問(wèn)哪個(gè)對(duì)象。僵尸對(duì)象可以解決這個(gè)問(wèn)題。
通過(guò)讓已經(jīng)被釋放的對(duì)象存活,Xcode可以告訴我們正在訪問(wèn)哪個(gè)被釋放的對(duì)象,進(jìn)而找到是什么原因引起的。
僵尸對(duì)象并不能把所有的EXC_BAD_ACCESS找出來(lái)。所以必須時(shí)需要通過(guò)下面的一些方式來(lái)解決——比如靜態(tài)分析。
靜態(tài)分析
如果僵尸對(duì)象不能解決問(wèn)題,可以通過(guò)靜態(tài)分析的方法來(lái)提前發(fā)現(xiàn)。
可以從Xcode中的Product中選則Analyze,或者直接Shfit+Command+B。Xcode將會(huì)花點(diǎn)時(shí)間把問(wèn)題的部分有問(wèn)題的代碼羅列出來(lái)。類似于:

當(dāng)點(diǎn)擊相關(guān)的issue時(shí),就會(huì)調(diào)到對(duì)應(yīng)的代碼位置。
Xcode只是會(huì)做出相應(yīng)的提示,在某些情況下,可能某些情況下不用修復(fù)。
- 如果不能準(zhǔn)確的定位問(wèn)題,那么就只通過(guò)靜態(tài)分析一個(gè)一個(gè)Issue去排查。
總結(jié)
EXC_BAD_ACCESS是一個(gè)比較常見的但同時(shí)也非常麻煩的問(wèn)題。這是問(wèn)題是從手動(dòng)管理內(nèi)存一直延續(xù)下來(lái)的,雖然現(xiàn)在大部分都是用ARC,但是并不會(huì)意味著EXC_BAD_ACCESS就消失。