先解釋一什麼叫 Static Code Analysis(簡稱SCT好了),顧名思義:不會動的時候分析一下code。也可以看到wikipedia的條目

這通常由自動化的工具來分析(不然,我想Code Review也算吧),主要希望能在source code 階段,發現一些邏輯上或程式相依上可以發現的潛在問題。有人會覺得這件事compiler不就會做了嗎?用gcc -Wall, 用vc /W4,開下去就幫你檢查完了。可是事實上compiler只會幫你檢查syntax是否符合語言的規範,一些邏輯上問題他不會幫你檢查,SCT就是補足這方面的不足。

舉例以C/C++來說(引用自klocwork)
Null Pointer dereference
如果 x = (11 12 13 14 16 17 18 19) ,就爆了

void foo(int* p) {
*p = 32;
}
void bar(int x) {
int* p = NULL;
if( x == 15 || x == 20 )
p = &x;
if( x > 10 && x <= 20 )
foo(p);
}


Buffer Overflow
如果 data 指向的string 大小大於32 ?

void foo(unsigned char* data) {
unsigned char value[32];
int len = (int)data [0];
memcpy(value, data + 1, len);
}


Memory Leak
嗯,多插2G ram

void foo() { malloc(32); }



除了邏輯上的問題,SCT也可以協助檢查style的問題,比如果在constructor請問intial list 來初始化成員,或功能強一的可以檢查是否符合"Effective C++"建議的條目,並提供一些統計數據讓開發者可以對自已的程式碼品值有一定的掌控度。
其實這種tool在早早以前就有,還記當時年紀小連class都不會寫的時候,跑去看圖書館看"C/C++ user journal"(停刊了,哭哭),側邊的廣告很多都是跟SCT相關。這樣的工具甘要錢,大概看了一下一套400us,但open source 界佛心來著,也提供了一套免錢的功能沒那麼強大工具,就是cppcheck
我自已是使用ubuntu,apt-get裝一下就有了,使用方法非常簡單,以我pcmanx-gtk為例,0.3.9為例

#-f 是檢查所有可能條件編譯的路徑
cppcheck --enable=all -f pcmanx-gtk/src


產生出的log大概長這樣

Checking src/appconfig.cpp: USE_DOCKLET...
[src/appconfig.cpp:54]: (style) Member variable not initialized in the constructor 'CAppConfig::ShowTrayIcon'
Checking src/appconfig.cpp: USE_EXTERNAL...
Checking src/appconfig.cpp: USE_MOUSE...
[src/appconfig.cpp:54]: (style) Member variable not initialized in the constructor 'CAppConfig::MouseSupport'
Checking src/appconfig.cpp: USE_PROXY...
Checking src/appconfig.cpp: USE_WGET...
[src/appconfig.cpp:54]: (style) Member variable not initialized in the constructor 'CAppConfig::UseWgetFiles'
Checking src/appconfig.cpp: __GNUG__...
1/41 files checked 2% done
Checking src/autologinpage.cpp...
2/41 files checked 4% done
Checking src/configfile.cpp...
Checking src/configfile.cpp: __GNUG__...
3/41 files checked 7% done


來看看他會檢查出什麼問題,底下是我節錄+整理的
style

[src/appconfig.cpp:54]: (style) Member variable not initialized in the constructor 'CAppConfig::SocketTimeout'
[src/core/caret.cpp:32]: (style) Member variable not initialized in the constructor 'CCaret::m_GC'
[src/core/fileutil.c:29]: (style) The scope of the variable fddest can be reduced
[src/core/termview.cpp:895]: (style) Redundant condition. It is safe to deallocate a NULL pointer


possible error

[src/editfavdlg.cpp:147]: (possible error) Memory leak: dlg
[src/editfavdlg.h:50]: (possible error) Memory leak: CEditFavDlg::m_List
[src/nancy_bot/msgdata.cpp:345]: (possible error) Memory leak: vsm


分析的結果只代表有修正的可能,不代表一定有錯,以memory leak 那項來說,只有2,3是真的有問題,第1個是因為gui的程式通常把child widget的釋放交給parent去做,所以不會有free的動作,還不賴吧。
除了cppcheck,也有另一套針對C語言的SCT open source 工具 splint,但是我搞不定他的設定,有人搞定可以教我一下嘛。另外最近事業做很大的clang/llvm,也提供一套C/C++/object-c的SCT工具,裝是裝起來了,但是怎麼試都不會有檢測報告,也請用過的人教一下吧

cmchao 發表在 痞客邦 PIXNET 留言(4) 人氣()