文章目錄
簡介
https://fbinfer.com/docs/getting-started
Infer
是一個靜態分析工具。Infer
可以分析 Objective-C
, Java
或者 C 代碼
,報告潛在的問題。
任何人都可以使用 Infer 檢測應用,這可以將那些嚴重的 bug 扼殺在發佈之前,同時防止應用崩潰和性能低下
關於Infer
特性可以去 https://fbinfer.com/ 查看
Infer效率高,規模大,幾分鐘能掃描數千行代碼;支持增量及非增量分析;分解分析,整合輸出結果。infer能將代碼分解,小範圍分析後再將結果整合在一起,兼顧分析的深度和速度。
使用
安裝
我們可通過Home Brew
進行快捷安裝。
brew install infer
如果brew
很慢,就使用個代理吧。文件挺大的。
或者你可以從github上拉下源碼,自己編譯
https://github.com/facebook/infer/blob/master/INSTALL.md#install-infer-from-source
一般來說這樣要快。
注:文檔中使用了opam
也是需要brew install opam
的
通過brew
安裝成功
設置 PATH 變量
如果使用brew install infer
安裝的話請忽略這步。
如果手動下載編譯就需要設置 PATH 變量
我們建議把 Infer 的執行目錄加入到環境變量中,這樣使用起來會簡便一些。當然,你也可以用絕對路徑。本文檔後續默認執行路徑已加入到環境變量中。
你可以使用以下命令設置環境變量。
cd infer-*v0\.\1\.0 &&
echo "export PATH=\"\$PATH:`pwd`/infer/infer/bin\"" \ >> ~/.bash_profile &&
source ~/.bash_profile
各種使用方式
https://fbinfer.com/docs/hello-world
官方文檔對各種case的使用說明的很詳細。
Object-C文件
對於 OC 單個文件分析,例如下面的 hello.m
#import <Foundation/Foundation.h>
@interface Hello: NSObject
@property NSString* s;
@end
@implementation Hello
NSString* m() {
Hello* hello = nil;
return hello.s;
}
@end
命令如下
infer run -- clang -c Hello.m
iOS工程 xcodebuild
- 創建一個
HelloWorldApp
工程 - 寫入有問題的文件
hello.h
和hello.m
#import <Foundation/Foundation.h>
@interface Hello: NSObject
@property NSString* s;
@end
@implementation Hello
NSString* m() {
Hello* hello = nil;
return hello->_s;
}
@end
- cd到工程目錄下,使用
infer run
infer run -- xcodebuild -project HCPushSettingViewController.xcodeproj -target HCPushSettingViewController -sdk iphoneos13.2
-sdk
版本請用xcodebuild -showsdks
查看
然後就生成了infer-out
文件
可以從文件中看到問題,同時有各種格式的結果文件,JSON
更便於其他系統集成,txt
便於我們自己人工查看
出錯時的兼容方法,使用Pod的工程
最健壯的方法是生成一個編譯數據庫,然後通過該數據庫推斷:
xcodebuild <your build options> | tee xcodebuild.log
xcpretty -r json-compilation-database -o compile_commands.json < xcodebuild.log > /dev/null
infer run --skip-analysis-in-path Pods --clang-compilation-db-files-escaped compile_commands.json
以HCPushSettingViewController
爲例子
先編譯數據database
xcodebuild -workspace HCPushSettingViewController.xcworkspace -scheme HCPushSettingViewController -sdk iphoneos13.2 | tee xcodebuild.log | xcpretty -r json-compilation-database -o compile_commands.json
然後執行
infer run --skip-analysis-in-path Pods --no-xcpretty --keep-going --clang-compilation-db-files-escaped compile_commands.json
我這裏使用了
--no-xcpretty --keep-going
,如不需要可以去掉
這裏提示
WARNING: '--clang-compilation-db-files-escaped' is deprecated. Use '--compilation-database-escaped' instead.
//即使用--compilation-database-escaped是新接口
如果直接執行infer run
的結果會報錯
** BUILD FAILED **
The following build commands failed:
Ld build/HCPushSettingViewController.build/Release-iphoneos/HCPushSettingViewController.build/Objects-normal/arm64/HCPushSettingViewController normal arm64
Ld build/HCPushSettingViewController.build/Release-iphoneos/HCPushSettingViewController.build/Objects-normal/armv7/HCPushSettingViewController normal armv7
(2 failures)
Internal Error: /usr/local/Cellar/infer/0.17.0/lib/infer/infer/bin/../lib/python/infer.py
-j 4 --project-root
/Users/sheng/Desktop/Git/HCPushSettingViewController/Samples --out
/Users/sheng/Desktop/Git/HCPushSettingViewController/Samples/infer-out --
xcodebuild -project HCPushSettingViewController.xcodeproj -target
HCPushSettingViewController -sdk iphoneos13.2:
exited with code 65
Error backtrace:
Raised at file "string.ml", line 145, characters 16-31
Called from file "string.ml" (inlined), line 149, characters 17-46
Called from file "src/string.ml", line 407, characters 12-33
Called from file "src/string.ml", line 416, characters 11-33
Re-raised at file "base/Die.ml", line 26, characters 8-56
Called from file "integration/Driver.ml", line 171, characters 2-16
Called from file "integration/Driver.ml", line 272, characters 6-409
Called from file "integration/Driver.ml", line 323, characters 2-29
Called from file "base/Utils.ml", line 398, characters 16-20
Called from file "scuba/ScubaLogging.ml", line 66, characters 29-44
Called from file "infer.ml", line 20, characters 2-36
Called from file "base/Utils.ml", line 398, characters 16-20
Called from file "scuba/ScubaLogging.ml", line 66, characters 29-44
Called from file "infer.ml", line 137, characters 8-54
所以這種方法能夠避免這些錯誤,因爲直接infer run
也是調用--xcpretty
來實現。
官方文檔:https://fbinfer.com/docs/analyzing-apps-or-projects
直接解析database
infer
也支持直接解析compile_commands.json
文件,其原理與OCLint
一致,都是基於Clang
。
infer --compilation-database compile_commands.json
*** Infer needs a working compilation command to run
add --no-xcpretty
https://github.com/facebook/infer/issues/759
xctool的支持
infer
也支持用xctool
替換xcodebuild
,使用xctool
生成一個編譯數據庫後再傳給infer
xctool.sh <your build options> -reporter json-compilation-database:compile_commands.json
infer run --skip-analysis-in-path Pods --clang-compilation-db-files-escaped compile_commands.json
github
上有相關資料 https://github.com/facebook/infer/issues/9#issuecomment-280121791
Unknown argument: ‘-index-store-path’
Xcode 9.0
將-index-store-path
添加到構建命令中。在clang
中還不支持它。在Build Setting
中搜索index
並將Enable Index-While-Building Functionality
選項設置爲NO
https://stackoverflow.com/questions/46331918/compilation-error-when-using-xcode-9-0-with-clang-cannot-specify-o-when-genera
增量模式、非增量模式
在第一次運行的時候,兩種模式是一樣的,都會對工程的所有文件進行編譯檢查,產生檢查結果:
增量模式
:當已經產生分析結果後(build和infer-out文件夾),再執行編譯命令,即爲增量模式。如有代碼沒有改動,則此次不會有編譯結果產生,如果代碼有新的改動,此次只產生新的編譯結果。這種以增量爲基準的原則叫做增量模式。
非增量模式
:在刪除了倆個文件夾(build和infer-out文件夾)的情況下,運行文件,會輸出所有的編譯信息,即此時處於非增量模式。
就是一個緩存刷新的問題,這裏可以刪除文件夾來使用非增量模式,使用--incremental
參數打開增量模式,或者使用xcodebuild
時,附加clean
配置
xcodebuild -target HelloWorldApp -configuration Debug -sdk iphonesimulator clean
原理
轉化階段
將源碼轉成infer
內部的中間語言。類C語言使用Clang
進行編譯,Java語言使用Javac
進行編譯,編譯的同時轉成中間語言,輸出到infer-out
目錄。
分析階段
分析infer-out
目錄下的文件。分析每個方法,如果出現錯誤的話會繼續分析下一個,不會被中斷,但是會記錄出錯位置,最後彙總。
每次運行,infer
都會刪除之前的infer-out
文件夾,可以通過--incremental
參數使用增量模式。
參考文章:
https://www.jianshu.com/p/b81a9f5bcf34
https://www.jianshu.com/p/4667e36aadea