iOS代碼靜態(tài)分析工具選擇

本文對(duì)比iOS常用的幾種靜態(tài)分析工具虾攻,分析優(yōu)缺點(diǎn),并從中選出適合當(dāng)前工程的工具延刘,本文的應(yīng)用系統(tǒng)為macOS镣隶。

clang

xcode目前已經(jīng)集成了clang了极谊,可以直接用Xcode-》Product-》Analyze對(duì)代碼進(jìn)行靜態(tài)分析。也可以用如下命令行實(shí)現(xiàn)

 cd Test
 xcodebuild analyze -project Test.xcodeproj -scheme Test -sdk iphonesimulator -configuration Debug CLANG_ANALYZER_OUTPUT=html CLANG_ANALYZER_OUTPUT_DIR="$(pwd)/clang"

clang會(huì)分析對(duì)應(yīng)工程的代碼安岂,并將結(jié)果輸出到clang文件夾下轻猖。
--html 生成分析結(jié)果的html文件。

  • clang的優(yōu)點(diǎn):
    跟xcode的集成度比較高域那,也支持命令行咙边,使用方便,解析速度較快。
  • 缺點(diǎn):
    檢查規(guī)則較少败许,這個(gè)在下文會(huì)有詳細(xì)介紹友瘤。

oclint

oclint也是iOS常用的代碼靜態(tài)分析工具,基于clang檐束。目前包含70個(gè)規(guī)則文件,基本涵蓋了clang的檢驗(yàn)規(guī)則束倍,并在此基礎(chǔ)上添加了較多代碼規(guī)范性規(guī)則被丧。可以在這里:http://docs.oclint.org/en/stable/rules/index.html查看具體規(guī)則绪妹。

  • 安裝
  brew tap oclint/formulae
  brew install oclint

或者直接到官網(wǎng)https://github.com/oclint/oclint/releases/tag/v20.11下載最新release版本解壓即可甥桂。

  #設(shè)置環(huán)境變量
  cd oclint-20.11
  export PATH=$pwd/oclint/bin:$PATH
  source ~/.bash_profile
  • 分析代碼
  cd Test
  xcodebuild -project Test.xcodeproj -scheme Test -configuration Debug -sdk iphonesimulator clean
  xcodebuild -project Test.xcodeproj -scheme Test -configuration Debug -sdk iphonesimulator | xcpretty -r json-compilation-database -o compile_commands.json 
  oclint-json-compilation-database -- -report-type html -o oclintReport.html

主要流程是通過(guò)xcodebuild編譯工程,之后用xcpretty輸出標(biāo)準(zhǔn)格式的json文件邮旷,最后oclint-json-compilation-database分析json文件黄选,并以html格式輸出結(jié)果。

  • oclint的優(yōu)點(diǎn):
    輸出結(jié)果的文件整潔好看婶肩,支持自定義規(guī)則办陷。
  • 缺點(diǎn):
    解析較慢,規(guī)則太多太雜律歼,很多都是代碼硬性規(guī)范民镜。

infer

infer是Facebook開(kāi)源的代碼靜態(tài)分析工具,同樣是基于clang险毁,可以分析c制圈、objC和java代碼。

  • 安裝
  brew install infer

或者通過(guò)源碼安裝畔况,可以從https://github.com/facebook/infer/blob/master/INSTALL.md了解源碼安裝的詳細(xì)步驟鲸鹦。
首先更新依賴(lài)庫(kù)

  brew install autoconf automake cmake opam pkg-config sqlite gmp mpfr
  brew cask install adoptopenjdk8

之后下載infer并build,這個(gè)過(guò)程可能需要1個(gè)多小時(shí)

  # Checkout Infer
  git clone https://github.com/facebook/infer.git
  cd infer
  # Compile Infer
  ./build-infer.sh clang
  # install Infer system-wide...
  sudo make install
  # ...or, alternatively, install Infer into your PATH
  export PATH=`pwd`/infer/bin:$PATH
  • 分析代碼
    infer分析代碼需要區(qū)分兩種情況跷跪,第一種沒(méi)有使用pods馋嗜、carthage等代碼依賴(lài)管理工具的工程,可以直接跑下面的命令進(jìn)行分析
  cd Test
  infer run -- xcodebuild -target Test -configuration Debug -sdk iphonesimulator

對(duì)于使用了pods域庇、carthage等代碼依賴(lài)管理工具的工程嵌戈,直接跑infer run命令會(huì)報(bào)錯(cuò),需要先利用xcodebuild和xcpretty去生成標(biāo)準(zhǔn)格式的json文件听皿,再用infer去分析它并輸出結(jié)果熟呛。

  cd Test
  xcodebuild -project Test.xcodeproj -scheme Test -configuration Debug -sdk iphonesimulator clean
  xcodebuild -project Test.xcodeproj -scheme Test -configuration Debug -sdk iphonesimulator | xcpretty -r json-compilation-database -o compile_commands.json
  infer run --keep-going --compilation-database-escaped compile_commands.json
  infer explore --html
  • 分析過(guò)程中可能遇到的問(wèn)題
  1. clang-9: error: unknown argument: '-index-store-path'
    這是因?yàn)閤code多了一個(gè)-index-store-path構(gòu)建命令,而infer跟oclint都不支持這個(gè)構(gòu)建命令尉姨,我們可以通過(guò)修改工程build setting中Enable index-While-Building Functionality設(shè)置為NO來(lái)避免這個(gè)問(wèn)題庵朝。
    當(dāng)然如果不想對(duì)工程配置做出修改,那么只需要在xcodebuild的時(shí)候設(shè)置對(duì)應(yīng)參數(shù)即可。
    xcodebuild -showBuildSettings查找'-index-store-path'對(duì)應(yīng)key值為COMPILER_INDEX_STORE_ENABLE九府,xcodebuild的時(shí)候椎瘟,將其置于NO,這樣對(duì)工程就不會(huì)有任何影響了侄旬。
  xcodebuild -project Test.xcodeproj -scheme Test -configuration Debug -sdk iphonesimulator COMPILER_INDEX_STORE_ENABLE=NO
  1. infer生成中間文件肺蔚,開(kāi)始掃描時(shí)報(bào)錯(cuò)
    需要注意的是,infer在一些環(huán)境下解析到最后一步會(huì)報(bào)錯(cuò)儡羔,并且輸出如下圖宣羊。這個(gè)問(wèn)題在infer的github上也有多人上報(bào),但目前并未解決汰蜘。但是慶幸的是仇冯,此時(shí)iner分析所需要的中間代碼文件已經(jīng)生成,所以只要在跑一次infer命令族操,即可生成最終結(jié)果苛坚。
    image.png
  • infer的優(yōu)點(diǎn):
    規(guī)則相對(duì)較完善,容易暴露開(kāi)發(fā)工程中可能引起問(wèn)題的代碼色难。
  • 缺點(diǎn):
    解析速度慢泼舱,且與oclint一樣有大量代碼硬性規(guī)范造成的誤報(bào)。

驗(yàn)證Demo

為了更直觀地對(duì)比幾種工具的分析結(jié)果莱预,筆者做了一個(gè)小demo列舉了一些開(kāi)發(fā)中常出現(xiàn)的不規(guī)范代碼柠掂,并分別用3種方式分析對(duì)比其結(jié)果。


截屏2020-12-03 下午10.33.45.png

通過(guò)clang掃描可以?huà)叱?未使用變量依沮、字典或者數(shù)組插入空值涯贞、參數(shù)類(lèi)型不匹配等幾種情況。
通過(guò)oclint掃描可以?huà)叱?未使用變量危喉、參數(shù)類(lèi)型不匹配以及一些命名規(guī)范類(lèi)的提示宋渔。
通過(guò)infer掃描可以?huà)叱?可選方法不安全調(diào)用、strong聲明為weak辜限、傳參類(lèi)型不匹配皇拣、未驗(yàn)空、字典或者數(shù)組插入空值等幾種情況薄嫡。

對(duì)比可以看出氧急,infer在檢驗(yàn)規(guī)則較多、定位也較為準(zhǔn)確毫深。所以目前筆者采用的是infer作為靜態(tài)分析工具吩坝。

小記:
靜態(tài)分析工具只是輔助,目前開(kāi)發(fā)中大量的代碼問(wèn)題沒(méi)法通過(guò)靜態(tài)分析定位哑蔫。諸如監(jiān)聽(tīng)未移除钉寝、timer未停止弧呐、野指針、應(yīng)用場(chǎng)景中導(dǎo)致的循環(huán)引用等都無(wú)法準(zhǔn)確定位嵌纲。所以開(kāi)發(fā)中還是需要養(yǎng)成良好的開(kāi)發(fā)習(xí)慣和代碼規(guī)范俘枫。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市逮走,隨后出現(xiàn)的幾起案子鸠蚪,更是在濱河造成了極大的恐慌,老刑警劉巖师溅,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件邓嘹,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡险胰,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)矿筝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)起便,“玉大人,你說(shuō)我怎么就攤上這事窖维∮茏郏” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵铸史,是天一觀的道長(zhǎng)鼻疮。 經(jīng)常有香客問(wèn)我,道長(zhǎng)琳轿,這世上最難降的妖魔是什么判沟? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮崭篡,結(jié)果婚禮上挪哄,老公的妹妹穿的比我還像新娘。我一直安慰自己琉闪,他們只是感情好迹炼,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著颠毙,像睡著了一般斯入。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蛀蜜,一...
    開(kāi)封第一講書(shū)人閱讀 51,482評(píng)論 1 302
  • 那天刻两,我揣著相機(jī)與錄音,去河邊找鬼涵防。 笑死闹伪,一個(gè)胖子當(dāng)著我的面吹牛沪铭,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播偏瓤,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼杀怠,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了厅克?” 一聲冷哼從身側(cè)響起赔退,我...
    開(kāi)封第一講書(shū)人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎证舟,沒(méi)想到半個(gè)月后硕旗,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡女责,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年漆枚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片抵知。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡墙基,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出刷喜,到底是詐尸還是另有隱情残制,我是刑警寧澤,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布掖疮,位于F島的核電站初茶,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏浊闪。R本人自食惡果不足惜恼布,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望搁宾。 院中可真熱鬧桥氏,春花似錦、人聲如沸猛铅。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)奸忽。三九已至堕伪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間栗菜,已是汗流浹背欠雌。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留疙筹,地道東北人富俄。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓禁炒,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親霍比。 傳聞我的和親對(duì)象是個(gè)殘疾皇子幕袱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容