Zombie
zombie的原理是用生成僵尸對象來替換dealloc的實現(xiàn),當對象引用計數(shù)為0的時候,將需要dealloc的對象轉化為僵尸對象。如果之后再給這個僵尸對象發(fā)消息,則拋出異常,并打印出相應的信息,調(diào)試者可以很輕松的找到異常發(fā)生位置。
AddressSanitizer
AddressSanitizer的原理是當程序創(chuàng)建變量分配一段內(nèi)存時,將此內(nèi)存后面的一段內(nèi)存也凍結住,標識為中毒內(nèi)存。
當程序訪問到中毒內(nèi)存時(越界訪問),就會拋出異常,并打印出相應log信息。調(diào)試者可以根據(jù)中斷位置和的log信息,識別bug。如果變量釋放了,變量所占的內(nèi)存也會標識為中毒內(nèi)存,這時候訪問這段內(nèi)存同樣會拋出異常(訪問已經(jīng)釋放的對象)。
AddressSanitizer 優(yōu)缺點
優(yōu)點:
AddressSanitizer比Zombie擁有更強大的捕獲能力,特別是在malloc對象和內(nèi)存越界方面,zombie幾乎無能為力。如果在debug的時候無法捕獲異常,上線之后crash log中概率性的EXC_BAD_ACCESS簡直是一種災難。
缺點:
1.AddressSanitizer可能會沒有l(wèi)og,不過會在訪問中毒內(nèi)存的代碼處斷住,這倒是對debug影響不大。
2.使用AddressSanitizer除了分配對象的內(nèi)存之外,還需要額外的內(nèi)存,這會導致App內(nèi)存大量增加,用起來有可能會比較卡。
總的來說,AddressSanitizer優(yōu)點大于缺點。
使用
在Xcode上方選擇設備的地方,點擊工程名字,選擇Edit Scheme。在Diagnostics中選中enable address sanitizer即可。
AddressSanitizer開啟之后,在debug過程中,如果遇到EXC_BAD_ACCESS的問題,Xcode會自動中斷,拋出異常
其他compiler flags
實際AddressSanitizer很早以前就有了,只是沒在Xcode中集成而已。除了AddressSanitizer還有很多其他的compiler flags,undefined-trap就是其中的一種。undefined-trap的功能也非常強大,它可以檢測出程序中的不明確行為,如數(shù)據(jù)溢出等。
下面我們以undefined-trap舉例,看看怎么用其他的compiler flags:
在Build Settings中的Custom Compiler Flags下為other C Flags添加-fsanitize=undefined-trap -fsanitize-undefined-trap-on-error
完成undefined-trap的設置之后,當程序的數(shù)據(jù)發(fā)生溢出行為時,系統(tǒng)就會拋出異常。
結束語:
經(jīng)過ARC的洗禮之后,普通的訪問釋放對象產(chǎn)生的EXC_BAD_ACCESS已經(jīng)大量減少了,現(xiàn)在出現(xiàn)的EXC_BAD_ACCESS有很大一部分來自malloc的對象或者越界訪問。簡單的敵人已經(jīng)被干掉,剩下的都是難纏的對手了。還好Apple給我們升級了裝備,以后遇到EXC_BAD_ACCESS應該不用那么心驚膽戰(zhàn)了吧?
參考文獻:
https://blog.csdn.net/xbenlang/article/details/49490563