隨著業(yè)務(wù)迭代,完全依靠人工保證代碼質(zhì)量變得很不靠譜攻晒,所以靜態(tài)分析工具變得很重要班挖;通過靜態(tài)語法分析能夠找出在代碼層面就能發(fā)現(xiàn)的內(nèi)存泄露問題,還可以通過上下文分析出是否存在變量無用等問題给梅。但是Xcode自帶的Analyze 的功能還是有限双揪,所以渔期,這才誕生出了功能更全渴邦、定制化高拘哨、效率高的第三方靜態(tài)檢查工具,如OCLint瓮床、Infer产镐、Clang 靜態(tài)分析器等癣亚;
綜合來看,Infer 在準(zhǔn)確性逃糟、性能效率绰咽、規(guī)則、擴展性取募、易用性整體度上的把握是做得最好的玩敏;
infer是Facebook 的 一個靜態(tài)分析工具≈簦可以分析 Objective-C砰粹, Java 或者 C 代碼,報告潛在的問題弄痹。
infer-項目地址為https://github.com/facebook/inferinfer-
中文網(wǎng)站https://infer.liaohuqiu.net
安裝infer可以參考文檔https://github.com/facebook/infer/blob/master/INSTALL.md
使用源碼安裝所需的時間會比較長嵌器,直接安裝 binary releases 會更快些爽航,在終端輸入:brew install infer
理論基礎(chǔ)
首先庇谆,infer是基于分離邏輯(Separation logic)和Bi-abduction 來實現(xiàn)的
那是什么是分離邏輯呢?凭疮??
分離邏輯是霍爾邏輯的一種擴展.霍爾邏輯是廣泛應(yīng)用的程序驗證邏輯系統(tǒng),用于對命令式語言程序 進行推理驗證.
基本思想是:在代碼段及其調(diào)用者之間構(gòu)建一種合同似的規(guī)格說明,由一個前置條件和一個后 置條件構(gòu)成.前置條件是一個斷言,描述這個代碼段執(zhí)行前程序狀態(tài)必須滿足的條件;后置條件也是一個斷言, 描述在代碼段正確運行后程序狀態(tài)所需要滿足的條件,調(diào)用者可以確信在代碼段執(zhí)行結(jié)束后這個狀態(tài)條件 為真串述。 在分離邏輯中,前置條件和后置條件中的程序狀態(tài)主要由棧S和堆H構(gòu)成,棧是變量到值的映射,而堆是有限的地址集合到值的映射.在程序驗證時,可以將椫唇猓看作對寄存器內(nèi)容的描述,而堆是對可尋址內(nèi)存內(nèi)容的描述.
分離邏輯簡而言之是推斷出存儲的獨立小部分的一種理論,從而不用考慮每一步存儲的完整性纲酗。因為考慮每一步的存儲完整性對當(dāng)今的大型可尋址虛擬內(nèi)存處理器來說工作量太龐大
infer 工作原理
- 第一階段是轉(zhuǎn)化衰腌,將源碼轉(zhuǎn)成infer內(nèi)部中間語言。c語言使用clang編譯觅赊,Java語言使用javac編譯右蕊,編譯同時轉(zhuǎn)成中間語言,輸出到infer-out目錄吮螺;
- 第二階段分析階段,分析infer-out目錄下文件每個方法鸠补,如果出現(xiàn)錯誤繼續(xù)分析下一個方法萝风,不會被中斷,但會記錄出錯位置紫岩,然后將所有出錯地方匯總輸出规惰;
infer 使用
分析單個文件 infer -- clang -c Hello.m
實際用這個命令去分析單個文件時報錯,懷疑是infer對最新的xcode兼容有問題泉蝌;分析整個工程
infer --keep-going --no-xcpretty -- xcodebuild -workspace xxx.xcworkspace -scheme xxx -configuration Debug -sdk iphonesimulator
試了好多命令歇万,這個可以分析完成,看分析結(jié)果bugs.txt文件
結(jié)果分析
在自己的工程目錄下會生成infer-out 文件夾勋陪,所有的問題都收錄在bugs.txt 中
問題類型匯總
DEAD_STORE 未使用的變量
DIRECT__ATOMIC_PROPERTY_ACCESS 原子屬性直接訪問贪磺,在代碼中使用了使用了一個atomic的成員變量,infer建議我們將atomic修改為nonatomic
ASSIGN___POINTER_WARNING assign修飾指針诅愚, 由于在mrc時代缘挽,沒有weak指針,所以一些view的屬性聲明是呻粹、unsafe__unretain_的形式壕曼,在arc中,這個屬性被判斷為assign等浊,需要將其修改為weak或者strong
NULL_DEREFERENCE
空指針的情況腮郊。根據(jù)具體代碼的不同,出現(xiàn)空指針的情況也有所不同筹燕。1.傳參為0的情況下轧飞。例如代碼中衅鹿,在調(diào)用showAlertViewA()時,將tag傳參為0,infer檢測此處傳0过咬,判斷為一個NULL空指針大渤,所以爆出警告。這里可以理解為誤報掸绞,不會出現(xiàn)問題泵三。2.通過malloc,calloc,realloc等函數(shù)申請內(nèi)存,當(dāng)內(nèi)存不足時衔掸,有可能會在該函數(shù)中返回NULL烫幕,如果沒有做NULL的判斷,則警告3.在創(chuàng)建NSArray或者NSDictionary時敞映,傳入的參數(shù)有可能會nil较曼。由于NSArray與NSDictionary不接受空指針,所以在對其addObject或者setObject:forKey: 時需要進行判斷一下是否為nil振愿。
POINTER__TO_CONST_OBJC_CLASS const錯誤用法
STRONG_DELEGATE_WARNING 將一個delegate屬性設(shè)置為strong的類型
PREMATURE_NIL_TERMINATION_ARGUMENT 提前nil終止
REGISTERED_OBSERVER_BEING_DEALLOCATED 監(jiān)聽沒有釋放捷犹,創(chuàng)建一個對象后,監(jiān)聽了某些通知冕末,但是沒有在dealloc中釋放該通知伏恐。項目中出現(xiàn)這種問題的類,基本都是單例栓霜,不會被銷毀
PARAMETER_NOT_NULL_CHECKED 參數(shù)非空檢查
MEMORY_LEAK 內(nèi)存泄露翠桦。項目代碼全面啟動了ARC進行內(nèi)存管理,在OC層沒有掃描出內(nèi)存泄露胳蛮。目前掃描出的內(nèi)存泄露問題都是使用了malloc或者ralloc等c語言內(nèi)存申請函數(shù)销凑,在函數(shù)提前return前沒有及時free