iOS Infer實現靜態分析器
隨著業務的開發迭代速度越來越快,完全依賴人工保證工程質量顯然顯得力不從心,所以公司本著開發效率為前提,我開始學習了靜態分析,它可以幫助我們在編碼的階段就可以及時發現程式碼錯誤,從而在根源上保證工程整體質量,也是我們iOS開發者最常用的一種程式碼除錯技術.
Xcode自帶的靜態分析工具Analyze,通過靜態語法分析能夠找出在程式碼層面就能發現的記憶體洩露問題,還可以通過上下文分析出是否存在無用變數等問題.但是Analyze的功能還是有限,還是無法幫助我們在編寫程式碼的階段發現更多的問題.所以我們這裡主要介紹一下我用的Infer靜態分析器.
Infer是Facebook開源的使用OCaml語言編寫的靜態分析工具,可以對C,java和Objective-C程式碼進行靜態分析,可以檢查出空指標訪問,資源洩露以及記憶體洩露.
安裝
安裝很簡單 直接在終端輸入:
brew install infer
接下來我們看一個事例
#import <Foundation/Foundation.h>
@interface Hello: NSObject
@property NSString* s;
@end
@implementation Hello
NSString* m() {
Hello* hello = nil;
return hello->_s;
}
@end
在終端輸入
infer -- clang -c hello.m
執行結果如下
Capturing in make/cc mode...
Found 1 source file to analyze in /Users/ming/Downloads/jikeshijian/infer-out
Starting analysis...
legend:
"F" analyzing a file
"." analyzing a procedure
F.
*Found 5 issues*
hello.m:10: error: NULL_DEREFERENCE
pointer `hello` last assigned on line 9 could be null and is dereferenced at line 10, column 12.
8. NSString* m() {
9. Hello* hello = nil;
10. *>* return hello->_s;
11. }
hello.m:10: warning: DIRECT_ATOMIC_PROPERTY_ACCESS
Direct access to ivar `_s` of an atomic property at line 10, column 12. Accessing an ivar of an atomic property makes the property nonatomic.
8. NSString* m() {
9. Hello* hello = nil;
10. *>* return hello->_s;
11. }
hello.m:4: warning: ASSIGN_POINTER_WARNING
Property `s` is a pointer type marked with the `assign` attribute at line 4, column 1. Use a different attribute like `strong` or `weak`.
2.
3. @interface Hello: NSObject
4. *>*@property NSString* s;
5. @end
6.
hello.m:10: warning: DIRECT_ATOMIC_PROPERTY_ACCESS
Direct access to ivar `_s` of an atomic property at line 10, column 12. Accessing an ivar of an atomic property makes the property nonatomic.
8. NSString* m() {
9. Hello* hello = nil;
10. *>* return hello->_s;
11. }
hello.m:4: warning: ASSIGN_POINTER_WARNING
Property `s` is a pointer type marked with the `assign` attribute at line 4, column 1. Use a different attribute like `strong` or `weak`.
2.
3. @interface Hello: NSObject
4. *>*@property NSString* s;
5. @end
6.
*Summary of the reports*
DIRECT_ATOMIC_PROPERTY_ACCESS: 2
ASSIGN_POINTER_WARNING: 2
NULL_DEREF
可以看出,我們前面的hello.m程式碼裡一共有誤個問題,其中一個包括一個錯誤四個警告.第一個錯誤如下:
hello.m:10: error: NULL_DEREFERENCE
pointer `hello` last assigned on line 9 could be null and is dereferenced at line 10, column 12.
8. NSString* m() {
9. Hello* hello = nil;
10. *>* return hello->_s;
11. }
這個錯誤資訊意思是,hello可能為空,需要去掉第10行12列的引用.我把這段程式碼修改下,去掉引用:
return hello.s;
在執行一遍infer命令:
infer -- clang -c hello.m
然後就發現只剩下一個警告了
hello.m:4: warning: ASSIGN_POINTER_WARNING
Property `s` is a pointer type marked with the `assign` attribute at line 4, column 1. Use a different attribute like `strong` or `weak`.
2.
3. @interface Hello: NSObject
4. *>*@property NSString* s;
5. @end
這個警告意思是說,屬性s是指標型別,需要使用strong或者weak修飾,這是我們將s的屬性改為strong再次執行infer,會發現沒有問題了,執行結果如下:
Capturing in make/cc mode...
Found 1 source file to analyze in /Users/ming/Downloads/jikeshijian/infer-out
Starting analysis...
legend:
"F" analyzing a file
"." analyzing a procedure
F.
*No issues found
Infer就是這麼的強大!很容易幫我們在編碼過程中避免一些不易發覺的問題,我自己才安裝這個工具,來這裡做個筆記