你好,歡迎來到IOS教程網

Infer

編輯:IOS開發基礎

寫在前面

本篇是一篇關於 Facebook 出品的靜態分析工具 Infer 的入門淺析,也可能你看到本篇文章的時候 我的 blog 裡面已經有了關於 Infer 的更多更進一步解析的文章又或者其他教程和分享,歡迎進入我的技術博客閱讀哈~。

對於一個穩定的項目來講,代碼靜態分析可謂不可或缺。當一個幾人甚至十幾人的團隊共同工作於一個項目時,考慮到離職、需求間的交叉改版都會使得團隊中的人不僅僅維護著自己負責的模塊,還要兼顧與自己責任模塊相關的需求開發以及維護。

由於需求的不斷改版人員的更替等等原因的影響,我們的代碼可能會犯一些意想不到的錯誤,這些錯誤可能很隱晦(你不得不承認對於一個剛進入項目的成員甚至實習生來說,之前的需求之間有哪些業務聯系並不是那麼容易掌握的),也可能是一些粗心的初級問題(比如聲明的變量到 2 期需求沒有用了,但是你只改了邏輯代碼沒有刪掉這個變量),隨著項目版本不斷迭代,問題日積月累成為了隱患。

那麼現在是時候來一波大掃除了,掃除掉項目中歷史代碼遺留下來的濃濃壞味道!

什麼是 Infer

Facebook 的 Infer 是一個由 OCaml 編寫的靜態分析工具。

Infer 可以分析 Objective-C, Java 或者 C 代碼,報告潛在的問題(這也是筆者安利 Infer 原因之一,可以分析 Java 後台以及 Android,瞬間把公司技術范圍靜態分析統一了有木有)。

任何人都可以使用 Infer 檢測應用,這可以將那些嚴重的 bug 扼殺在發布之前,同時防止應用崩潰和性能低下。

1644823-ef83af1b83b1810a.png

特性

Android 和 Java

Infer 可檢查 Android 和 Java 代碼中的 NullPointException 和 資源洩露。

iOS

除了以上,Infer 還可發現 iOS 和 C 代碼中的內存洩露。

誰在使用 Infer?

Infer 已經成為 Facebook 開發流程的一個環節,包括 Facebook Android 和 iOS 主客戶端,Facebook Messenger, Instagram 在內的,以及其他影響億萬用戶的手機應用,每次代碼變更,都要經過 Infer 的檢測(可以說 Facebook 在開源 Infer 之前,Facebook 的開發團隊在代碼提交內部評審時,都是用 Infer 執行靜態分析的)。

1644823-e991a2bd29a479af.png

安裝 Infer

Note:
Infer 依賴環境 - Python 版本 >= 2.7

mac

如果你已經安裝 Homebrew 就可以簡單的在終端輸入一下命令來安裝:

brew install infer

Linux

最簡單的方法是通過 Docker 來安裝:

wget -O Dockerfile https://raw.githubusercontent.com/facebook/infer/master/docker/Dockerfilewget -O run.sh https://raw.githubusercontent.com/facebook/infer/master/docker/run.sh
sh run.sh

通過資源安裝

可以從最新的 GitHub release 安裝預編譯版本 Infer。
你需要先安裝並 建立依賴關系,然後執行一下命令:

tar xf infer-.tar.xzcd infer-/
./build-infer.shexport PATH=`pwd`/infer/bin:$PATH

在浏覽器中試用 Infer

如果你想先在浏覽器中通過一個簡單的示例來試用 Infer 的話,點擊 Codeboard.

一個簡單的使用 Infer 分析 iOS 代碼實例

首先,先舉例一份有問題的代碼:

// Hello.m#import @interface Hello: NSObject@property NSString* s;@end@implementation HelloNSString* m() {
    Hello* hello = nil;    return hello->_s;  // 問題代碼}@end

啟動終端,在 Hello.m 文件所在的文件夾下輸入命令:

infer -- clang -c Hello.m

你將會看到 Infer 報告的以下問題:

Hello.m:10 NULL_DEREFERENCE
  pointer hello last assigned on line 9 could be null and is dereferenced at line 10, column

現在修改代碼:

NSString* m() {
    Hello* hello = nil;    return hello.s;
}

再次運行 Infer,發現 Infer 沒有報任何問題。

使用 Infer 的幾點注意事項

Infer 區分增量/非增量分析:

  • 增量分析表示每次只對新增或者修改的代碼做靜態分析,忽視掉之前已經分析過的代碼

  • 非增量分析表示每次都會分析項目中的所有代碼,不論之前是否已經分析過

其他注意事項

  • 確保你的項目在你第一次運行 Infer 靜態分析之前是干淨的(make clean, or gradle clean)

  • 當你運行 Infer 分析代碼時發現在某一行代碼上重復分析了幾次,可以嘗試第一步 clean 你的項目,或者加入 --reactive 到 Infer 的命令

  • 如果你不需要增量分析的話則不需要執行這些步驟,例如:你正在分析單個源代碼文件

  • 如果當你成功運行 Infer 之後還想要得到更為詳細的報告時,可以通過在相同的文件夾下運行 inferTraceBugs 來辦到

解讀 Infer 工作流

當你成功的運行 Infer 解析一個簡單的項目後會發現項目目錄下多出了兩個文件夾:build & infer-out。下面會解釋這兩個文件夾是怎麼產生的。

不論你是用 Infer 分析 C、Objective-C 還是 Java,Infer 的分析工作主要分為兩個階段:

1. 捕獲階段

Infer 通過把你的代碼轉譯為 Infer 自己的中間語言來做靜態分析。

這種轉譯依賴於編譯,所以 Infer 需要從編譯過程中獲取信息來執行自己的轉譯。這就是為什麼我們調用 Infer 的時候要加上編譯命令:infer -- javac File.javainfer -- clang -c file.c

當我們輸入上述命令時,除了源代碼文件被正常編譯的同時,它們同時被 Infer 轉譯以用作第二階段。

Note: 如果沒有被編譯的文件,也沒有文件將被分析。

Infer 將捕獲階段創建的中間文件存儲在 infer-out 文件夾中,你也可以修改文件夾的名稱 option -o

2. 分析階段

在這個階段中,上述 infer-out 文件夾中的文件被靜態分析,Infer 將分別對每個 foundation 和 method 進行分析推斷。如果 Infer 在分析某個函數時遇到了 error,那麼 Infer 會停在該方法中,不會繼續分析其他的函數(⊙﹏⊙)b,所以一般你的工作流程是這樣的:

  • Infer 對你的項目代碼做靜態分析

  • 分析遇到 error 並報給你

  • 修復該問題代碼

  • 且再次運行 Infer 對你的項目代碼做靜態分析(回跳第一步)

當 Infer 分析代碼後,會將發現的問題記錄並保存到文件 infer-out/bugs.txt 中。

在 infer-out 文件夾下,Infer 還將生成一個文件 report.csv,其中包含所有 Infer 在靜態分析過程中發現的錯誤,警告和相關信息,當然他們都是 csv 格式的。

探索 Infer Report

你可以在項目文件夾下通過inferTraceBugs命令來從 report 文件中獲取更多的信息:

infer -- gradle buildinferTraceBugs

這個工具可以幫助你看到錯誤產生的軌跡,幫助你跟蹤每一個錯誤的真正原因。你可以使用命令inferTraceBugs --help來查看更多信息。




  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved