BAD_ACCESS 在什么情況下出現(xiàn)
BAD_ACCESS?報錯屬于內(nèi)存訪問錯誤,會導(dǎo)致程序崩潰,錯誤的原因是訪問了野指針(懸掛指針)。野指針指的是本來指針指向的對象已經(jīng)釋放了,但指向該對象的指針沒有置 nil,指針指向隨機的未知的內(nèi)存,程序還以為該指針指向那個對象,導(dǎo)致存在一些潛在的危險訪問操作,這些危險訪問操作無法被指針指向的未知內(nèi)存所處理,就會導(dǎo)致BAD_ACCESS錯誤造成程序崩潰。訪問的含義包括多種情況,例如:向野指針發(fā)送消息,讀寫野指針本來指向的對象的成員變量等等。
首先調(diào)試BAD_ACCESS錯誤是比較困難的,我們知道BAD_ACCESS錯誤是由于訪問了野指針,但程序不會在野指針出現(xiàn)時或者在我們訪問野指針的代碼處報錯,導(dǎo)致對其難以察覺,調(diào)試方法思路如下:
開啟僵尸對象診斷
首先是開啟僵尸對象診斷模式,利用僵尸對象來對野指針的出現(xiàn)位置提供線索。我們知道僵尸對象指的是引用計數(shù)為0被系統(tǒng)回收的對象,但這些對象暫時還存在于內(nèi)存中,且理論上還是可以使用的,但是不穩(wěn)定。開啟僵尸對象診斷后,僵尸對象會暫時保持活躍用于調(diào)試,我們的野指針在對象回收后依然指向該僵尸對象,在訪問野指針也就是訪問僵尸對象的情況下可以被編輯器檢測出來。這個時候還是會報BAD_ACCESS錯誤,但是后臺會打印出該線索,例如下面的訪問野指針打印的后臺信息:
2017-03-1216:28:31.501Debug[2371:1379247]-[TestViewController respondsToSelector:]messagesenttodeallocatedinstance0x16749682
1
2
可以看出Xcode告訴我們消息發(fā)送給了一個僵尸對象,僵尸對象原本是TestViewController的一個實例,但現(xiàn)在該對象被回收了而開發(fā)者還試圖訪問它,由此可以很容易定位問題所在。
另外開啟僵尸對象診斷的方法為:打開Xcode頂部導(dǎo)航欄的Product-Scheme-Edit Scheme,在彈出的界面中選中左側(cè)的Run模式,然后勾選右側(cè)Dianostics下的Zombie Objects。不同版本Xcode可能選項位置略有差異,此處為最新的Xcode 8.2.1。
Analyze分析
僵尸對象診斷可以幫助快速定位多數(shù)情況下的野指針問題,但也有時候不能奏效,這個時候只能利用Xcode的Analyze靜態(tài)分析幫助檢查可能出問題的地方,仔細(xì)檢查問題所在,比較費時。
使用方法很簡單,選中Xcode頂部導(dǎo)航欄Product-Analyze或使用快捷鍵Command+Shift+B,分析需要花一些時間,然后左側(cè)會列出編輯器發(fā)現(xiàn)的存在潛在問題的地方,選中藍(lán)色圖標(biāo)對應(yīng)的問題項會跳到問題項所在的代碼行。但這只能給出一些潛在提示,幫助搜索問題所在,不一定和我們的bug相關(guān)。