iOS調(diào)試(1): BAD_ACCESS錯(cuò)誤原因和僵尸調(diào)試方法

在iOS開發(fā)過(guò)程中,偶爾會(huì)遇到 EXC_BAD_ACCESS 造成的崩潰,本文著重講解什么是 EXC_BAD_ACCESS ,以及它產(chǎn)生的原因,還有針對(duì) EXC_BAD_ACCESS 錯(cuò)誤的解決方案。
原文鏈接:http://www.cocoachina.com/ios/20160226/15324.html

1、什么是 EXC_BAD_ACCESS

a. 簡(jiǎn)單的解釋
不管什么時(shí)候當(dāng)你遇到EXC_BAD_ACCESS這個(gè)錯(cuò)誤,那就意味著你向一個(gè)已經(jīng)釋放的對(duì)象發(fā)送消息。這是最常見的情況,其他的情況,我們將在稍后討論。

b. EXC_BAD_ACCESS 的本質(zhì)
在C和Objective-C中,你一直在處理指針。指針無(wú)非是存儲(chǔ)另一個(gè)變量的內(nèi)存地址的變量。當(dāng)您向一個(gè)對(duì)象發(fā)送消息時(shí),指向該對(duì)象的指針將會(huì)被引用。這意味著,你獲取了指針?biāo)傅膬?nèi)存地址,并訪問(wèn)該存儲(chǔ)區(qū)域的值。

當(dāng)該存儲(chǔ)器區(qū)域不再映射到您的應(yīng)用時(shí),或者換句話說(shuō),該內(nèi)存區(qū)域在你認(rèn)為使用的時(shí)候卻沒有使用,該內(nèi)存區(qū)域是無(wú)法訪問(wèn)的。 這時(shí)內(nèi)核會(huì)拋出一個(gè)異常( EXC ),表明你的應(yīng)用程序不能訪問(wèn)該存儲(chǔ)器區(qū)域(BAD ACCESS) 。

當(dāng)你碰到EXC_BAD_ACCESS ,這意味著你試圖發(fā)送消息到的內(nèi)存塊,但內(nèi)存塊無(wú)法執(zhí)行該消息。但是,在某些情況下, EXC_BAD_ACCESS是由被損壞的指針引起的。每當(dāng)你的應(yīng)用程序嘗試引用損壞的指針,一個(gè)異常就會(huì)被內(nèi)核拋出。

2、調(diào)試 EXC_BAD_ACCESS

a. 面臨的困難
調(diào)試EXC_BAD_ACCESS可能會(huì)非常棘手,因?yàn)槟膽?yīng)用程序并不一定是在崩潰的那一刻,無(wú)法訪問(wèn)內(nèi)存區(qū)域。這就是常使調(diào)試EXC_BAD_ACCESS變得困難的原因。

同樣受損指針也是如此。當(dāng)你的指針被損壞時(shí),您的應(yīng)用程序不會(huì)崩潰。同時(shí),如果您在應(yīng)用程序中來(lái)回傳遞一個(gè)受損的指針也不會(huì)崩潰。當(dāng)應(yīng)用程序試圖引用受損指針的時(shí)候,就會(huì)發(fā)生崩潰。

b. 僵尸調(diào)試模式
僵尸聽起來(lái)有點(diǎn)戲劇性,但它實(shí)際上是為幫助我們調(diào)試 EXC_BAD_ACCESS 功能而取得一個(gè)偉大的名字。讓我來(lái)解釋它是如何工作的。

在Xcode中,您可以啟用僵尸對(duì)象,這意味著被釋放的對(duì)象將會(huì)以僵尸的形式被保留。換言之,保留釋放的對(duì)象就是為了調(diào)試。這里沒有涉及任何魔法。如果您向僵尸對(duì)象發(fā)送消息,你的應(yīng)用程序?qū)?huì)由于 EXC_BAD_ACCESS 而崩潰。

這樣做的好處在于,讓EXC_BAD_ACCESS難以調(diào)試的原因是,你不知道你的應(yīng)用程序試圖訪問(wèn)哪個(gè)對(duì)象。僵尸對(duì)象在許多情況下解決這個(gè)問(wèn)題。通過(guò)保留已釋放的對(duì)象,Xcode可以告訴你你試圖訪問(wèn)哪個(gè)對(duì)象,這使的查找問(wèn)題原因容易得多。

在Xcode中啟用僵尸對(duì)象是很容易的。注意,這可能會(huì)因的Xcode的版本而不同的。以下方法適用于Xcode的8,單擊左上角的Edit Scheme,并選中Edit Scheme。

在左側(cè)選中Run ,在上方打開 Diagnostics選項(xiàng)。要啟用僵尸對(duì)象,勾選 Enable Zombie Objects選框。

image.png

這時(shí)如果遇到 EXC_BAD_ACCESS ,在Xcode的控制臺(tái)輸出,會(huì)告訴你問(wèn)題出在哪里。

2015-08-12 06:31:55.501 Debug[2371:1379247] -[ChildViewController respondsToSelector:] message sent to deallocated instance 0x17579780

在上面的例子中, Xcode告訴我們, respondsToSelector的消息:被發(fā)送到一個(gè)僵尸對(duì)象。然而,僵尸對(duì)象不再是ChildViewController類的一個(gè)實(shí)例。以前分配給ChildViewController實(shí)例的內(nèi)存區(qū)域不再映射到您的應(yīng)用程序。這為你了解問(wèn)題產(chǎn)生的根本原因提供一個(gè)不錯(cuò)的建議。

不幸的是,僵尸對(duì)象將無(wú)法保存您的一天每次崩潰的EXC_BAD_ACCESS的記錄。既然僵尸對(duì)象沒有這些方法,那么你可以采取其他的方法進(jìn)行一些適當(dāng)?shù)姆治觥?/p>

c. 分析
如果僵尸對(duì)象不能解決你的問(wèn)題,那么問(wèn)題的根源可能就不那么簡(jiǎn)單了。在這種情況下,您需要仔細(xì)看看在應(yīng)用程序崩潰時(shí)執(zhí)行的代碼。這可能是繁瑣和耗時(shí)的。

為了幫助你發(fā)現(xiàn)你的代碼的問(wèn)題,你可以使用Xcode來(lái)分析你的代碼,幫助你找到出現(xiàn)問(wèn)題的地方。注意,Xcode分析項(xiàng)目,它會(huì)指出每一個(gè)潛在的可能出現(xiàn)的問(wèn)題的地方。

使用Xcode來(lái)分析你的項(xiàng)目,從Xcode的 Product菜單選擇 Analyze或按 Shift-Command-B.Xcode的將需要片刻的時(shí)間,但是當(dāng)它完成的時(shí)候你會(huì)在左邊的 Issue Navigator看到問(wèn)題列表。由Analyze發(fā)現(xiàn)的問(wèn)題用藍(lán)色高亮顯示。

image.png

當(dāng)你點(diǎn)擊一個(gè)問(wèn)題,Xcode的會(huì)指向問(wèn)題代碼塊,這些正是你要的注意的地方。注意,Xcode僅僅是建議。在某些情況下,這是可能的,問(wèn)題是不相關(guān)的,不固定。

image.png

如果你找不到造成EXC_BAD_ACCESS的錯(cuò)誤,那就需要你仔細(xì)審視Xcode項(xiàng)目,分析其中發(fā)現(xiàn)的每一個(gè)問(wèn)題。

3、結(jié)論

EXC_BAD_ACCESS 是開發(fā)者面臨的一個(gè)共同的問(wèn)題,它是手動(dòng)內(nèi)存管理固有的問(wèn)題。雖然推行ARC內(nèi)存管理方式 (自動(dòng)引用計(jì)數(shù))使得EXC_BAD_ACCESS沒那么頻繁,但他們并沒有真正的消失。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容