C/C++怎么做好代碼靜態(tài)分析

代碼靜態(tài)分析

代碼靜態(tài)分析是指在不運(yùn)行代碼的情況下根據(jù)代碼的靜態(tài)信息,對代碼的各個(gè)維度進(jìn)行分析。

代碼靜態(tài)分析一般包括如下三個(gè)方面:

  • 編碼規(guī)范檢查:保證代碼的風(fēng)格和團(tuán)隊(duì)的要求一致,對于多人合作的軟件項(xiàng)目,這是代碼易于理解和維護(hù)的基本要求。
  • 代碼靜態(tài)度量:一般指代碼復(fù)雜度度量,包括分支復(fù)雜度、圈復(fù)雜度、代碼深度等。除此之外還包括代碼重復(fù)率等指標(biāo)。
  • 代碼缺陷檢查:指通過靜態(tài)分析發(fā)掘代碼潛在的故障和缺陷。例如空指針異常、內(nèi)存越界、堆棧溢出等潛在的軟件bug。由于只是基于靜態(tài)代碼分析,所以故障缺陷只是意味存在著一個(gè)潛在的故障可能,仍需要人工事后分析。

代碼靜態(tài)分析可以通過人工分析和工具分析兩種途徑。人工分析也就是我們熟知的代碼走查,被認(rèn)為是一項(xiàng)提高軟件質(zhì)量非常有效的實(shí)踐活動(dòng)。然而對于擁有巨大代碼庫的軟件,人工檢查成本大,而且枯燥重復(fù),這時(shí)借助工具可以大大提高代碼靜態(tài)檢查的效率。讓工具覆蓋常見低級缺陷,進(jìn)行大規(guī)模掃描,而讓人去關(guān)注邏輯性強(qiáng)的分析檢查,可以有效發(fā)揮工具和人的長處。另外工具也讓自動(dòng)化變?yōu)榭赡?,可以有效提高工程效率?/p>

代碼靜態(tài)分析的價(jià)值

對于軟件,故障發(fā)現(xiàn)的時(shí)間越晚修復(fù)的成本會成指數(shù)上升趨勢。有效的代碼靜態(tài)分析能夠在軟件運(yùn)行之前暴露潛在的軟件問題,對于大的軟件項(xiàng)目可以節(jié)省巨大的成本。通過代碼靜態(tài)檢查,可以獲得如下收益:

  • 可以提早發(fā)現(xiàn)代碼的風(fēng)格問題,第一時(shí)間對代碼風(fēng)格進(jìn)行統(tǒng)一;
  • 可以盡早的得到代碼的度量數(shù)據(jù),對代碼的復(fù)雜度提供可靠數(shù)據(jù),以指導(dǎo)重構(gòu)工作的開展;
  • 發(fā)現(xiàn)潛在的代碼故障,避免故障泄露到后續(xù)的運(yùn)行期,節(jié)省故障的定位成本和解決成本;

最后,將代碼靜態(tài)分析工具部署在持續(xù)集成服務(wù)器上,可以實(shí)時(shí)獲得上述反饋。通過持續(xù)集成的實(shí)時(shí)監(jiān)控和反饋,可以持續(xù)地防范代碼的腐化和缺陷。

代碼靜態(tài)分析的途徑

代碼走查

一說起代碼靜態(tài)分析,人們往往先想到的是靜態(tài)檢查工具。事實(shí)上根據(jù)業(yè)界的統(tǒng)計(jì),最有效的代碼靜態(tài)分析反而是人工代碼走查。但是傳統(tǒng)的人工走查由于缺少工具和流程的支撐,容易流為形式,因此Google和Facebook等企業(yè)都研發(fā)了簡單易用的代碼走查工具,并將代碼走查活動(dòng)部署在代碼提交的關(guān)鍵路徑上,使其成為代碼提交流程的一部分。借助工具讓代碼走查變得不再麻煩,并通過將這一實(shí)踐固化在代碼提交流程中而避免了實(shí)踐遺漏。

例如當(dāng)前流行的Code Review工具:Facebook開源的Phabricator。Phabricator需要一臺服務(wù)器進(jìn)行部署,并配置和代碼倉庫(例如SVN)進(jìn)行連接。開發(fā)人員代碼提交會自動(dòng)觸發(fā)Phabricator發(fā)起一次代碼評審活動(dòng),只有根據(jù)評審意見修改了代碼被認(rèn)定評審?fù)ㄟ^,代碼才會被準(zhǔn)許提交進(jìn)SVN中。這一切都由Phabricator進(jìn)行流程控制。另外Phabricator提供了一個(gè)交互式網(wǎng)頁服務(wù),在上面可以針對代碼逐行評審并提交評審意見,被評審者可以對評審意見作出回復(fù)。可見Phabricator還提供了一個(gè)評審意見交流平臺。

另外一個(gè)類似的工具是Gerrit,主要針對git倉庫。

工具檢查

通過工具對代碼進(jìn)行靜態(tài)分析檢查是一種更加高效的手段。靜態(tài)分析工具一般分為靜態(tài)度量工具和靜態(tài)檢查工具。

代碼靜態(tài)度量工具

靜態(tài)度量工具主要是對代碼進(jìn)行靜態(tài)復(fù)雜度度量?;镜陌ùa行數(shù),函數(shù)數(shù)等,再下來就是分支復(fù)雜度,圈復(fù)雜度,代碼深度等等,通過這些數(shù)據(jù),可以展現(xiàn)當(dāng)前的代碼規(guī)模以及復(fù)雜度情況。復(fù)雜度結(jié)果為代碼提供了可視化數(shù)據(jù),可以對代碼的重構(gòu)提供指導(dǎo),還可以借助復(fù)雜度度量結(jié)果對代碼的重構(gòu)效果進(jìn)行度量。另外將復(fù)雜度檢查工具集成進(jìn)持續(xù)集成服務(wù)器的話,可以設(shè)置規(guī)則避免過高復(fù)雜度的代碼入庫。新提交的代碼只有在滿足復(fù)雜度要求的情況下才允許合入代碼庫,這可以在第一時(shí)間防止代碼腐化。目前大多數(shù)語言都可以找到開源易用的復(fù)雜度度量工具,這些工具有些可以直接集成進(jìn)開發(fā)IDE工具中,讓開發(fā)人員在寫代碼的時(shí)候就能獲得度量結(jié)果。

代碼靜態(tài)檢查工具

靜態(tài)檢查工具主要是通過掃描發(fā)掘代碼中隱藏的潛在故障。一般通過以下維度衡量一個(gè)代碼靜態(tài)檢查工具:

  • 檢查規(guī)則數(shù):支持的檢查規(guī)則越多則能發(fā)現(xiàn)越多的潛在故障;
  • 誤報(bào)率:指在報(bào)告的潛在故障中,非真實(shí)故障所在的比率。誤報(bào)率越低越好;
  • 易用性:有的工具支持本地部署檢查,有的則需要把所有的檢查數(shù)據(jù)上傳服務(wù)器。不同工具的易用性差別挺大;
  • 收費(fèi)模式:免費(fèi)還是收費(fèi),收費(fèi)的話收費(fèi)模式如何;

遺憾的是對于C/C++,當(dāng)前市面上功能強(qiáng)大的代碼靜態(tài)檢查工具皆是商用的。開源的工具在規(guī)則數(shù)以及對潛在故障的挖掘深度上和商用工具的差距還是挺明顯的。一般由于商用工具比較昂貴,所以大多企業(yè)會選擇將開源和收費(fèi)工具結(jié)合使用,只在關(guān)鍵項(xiàng)目階段部署使用商用工具,而開發(fā)人員日常掃描則使用開源工具。當(dāng)然具體策略需要和產(chǎn)品類型項(xiàng)目情況等相結(jié)合。

代碼靜態(tài)分析工具對比

對于C++語言,代碼度量工具大多選擇SourceMonitor,這款軟件是免費(fèi)的,功能包括基本的代碼行、函數(shù)數(shù)量、類數(shù)量統(tǒng)計(jì),還包括分支比例度量、圈復(fù)雜度度量、代碼深度度量等,并且會根據(jù)度量結(jié)果生成報(bào)表。

C++的代碼靜態(tài)檢查工具,常用的有cppcheck、pclint、coverity等,這些軟件除了可以檢查代碼規(guī)范,還可以掃描分析代碼的潛在故障。我們按照以下維度進(jìn)行對比:

對比項(xiàng) cppcheck pclint coverity klocwork
收費(fèi)模式 免費(fèi) PC license $389 多模式收費(fèi);和代碼規(guī)模和license類型有關(guān)。網(wǎng)站沒有明確報(bào)價(jià),具體報(bào)價(jià)需要咨詢客服 收費(fèi);網(wǎng)站沒有明確報(bào)價(jià),需要根據(jù)軟件規(guī)模和license類型具體咨詢客服
支持語言 C/C++ C/C++ C/C++/Java/C# C/C++/Java/C#
支持平臺 跨平臺 跨平臺 跨平臺 跨平臺
支持Jenkins集成 支持 支持 支持 通過第三方插件
掃描結(jié)果 本地報(bào)表 本地結(jié)果 需上傳服務(wù)器 需上傳服務(wù)器
規(guī)則數(shù) 200+ 900+ 500+ 沒有官方數(shù)字
誤報(bào)率 中等
易用性 易用 易用 復(fù)雜 復(fù)雜

從前面的分析可見,雖然開源的工具易用性高、容易和持續(xù)集成服務(wù)器進(jìn)行集成,但缺點(diǎn)是掃描效果無論是在深度和廣度上都不如商業(yè)工具。另外規(guī)則數(shù)越多誤報(bào)率就越高,所以這是一個(gè)需要平衡的點(diǎn)。

代碼靜態(tài)分析工具部署

對于代碼靜態(tài)度量工具,由于是開源免費(fèi)的,一般開發(fā)人員和持續(xù)集成服務(wù)器上都進(jìn)行部署。開發(fā)人員代碼提交前先自檢,自檢復(fù)雜度在要求范圍內(nèi)再提交入庫。而持續(xù)集成服務(wù)器通過統(tǒng)一構(gòu)建再進(jìn)行確認(rèn)。

而對于代碼靜態(tài)檢查工具,從前面的分析可見,雖然開源的工具易用性高、容易和持續(xù)集成服務(wù)器進(jìn)行集成,但缺點(diǎn)是掃描效果無論是在深度和廣度上都不如商業(yè)工具。但這并不能說開源工具就沒有了價(jià)值。一般項(xiàng)目的做法是在軟件流水線的不同階段部署不同的工具,來達(dá)到整體成本收益比最好。

一種常見的部署方式是,在每個(gè)開發(fā)人員的機(jī)器上部署cppcheck開源工具,這樣每個(gè)開發(fā)人員都可以在本地實(shí)時(shí)對代碼進(jìn)行檢查,將初級的錯(cuò)誤直接消滅在本地。而持續(xù)集成上則部署商業(yè)靜態(tài)檢查工具,這樣可以降低商業(yè)工具部署的機(jī)器數(shù),還能降低商業(yè)工具的掃描次數(shù),從而節(jié)省費(fèi)用開支。一般在持續(xù)集成上可以設(shè)置每日或者每個(gè)發(fā)布版本用商業(yè)工具進(jìn)行一次掃描,具體配置規(guī)則和項(xiàng)目特點(diǎn)有關(guān)。

集成了代碼走查工具,代碼度量工具和代碼檢查工具的持續(xù)集成服務(wù)器如下圖。

其它注意事項(xiàng)

  • 在代碼靜態(tài)檢查之前,最好先將編譯告警也消除掉。從檢查基礎(chǔ)的修復(fù)開始做起。
  • 對檢查工具報(bào)的錯(cuò)誤要第一時(shí)間修復(fù),不要累計(jì)。大規(guī)模修改引入的風(fēng)險(xiǎn)往往不可控。
  • 由于工具會有誤報(bào),所以使用工具仍避免不了人工分析,人工分析的質(zhì)量仍需要保證。
  • 不要因?yàn)橛辛斯ぞ叨雎粤巳斯ごa走查的重要性。
  • 由于靜態(tài)分析只是依據(jù)代碼的靜態(tài)視圖做分析,不能替代代碼的運(yùn)行態(tài)測試,例如單元測試。

相關(guān)推薦材料

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容