筆者接手的這些 Keil C 程式(ARM based),自然是沒辦法放到 Linux 上編譯
、然後用 gprof + graphviz 加以分析(加上 SoC 是公司自行設計)。
除了無限期試用版 SourceInsight 外,還有什麼方法可以在前人留下的程式海中自救呢?筆者最近從網路上找到了兩只救生圈,用起來感覺還不錯,推薦給大家。
cflow2dot
從字面上就可以看出來是 "cflow to dot",dot 就是指 graphviz,這在前面提過了,這邊就不浪費篇幅解釋。cflow 其實多年前筆者就用過 Windows console 版,其實他就是一個把 c source code 裡面除了函數呼叫外的東西通通刪掉、只留下函數呼叫的工具。比方下面這個範例:
/* main.c */ int main(int argc, char **argv) { foo(); bar(); return 0; } /* foo.c */ void foo(void) { printf("foo\n"); xyz(); } /* bar.c */ void bar(void) { printf("bar\n"); xyz(); } /* xyz.c */ void xyz(void) { printf("xyz\n"); }執行命令:
$ cflow main.c輸出結果:
main() <int main (int argc, char **argv) at main.c:2>: foo() bar()不過這跟想像有點出入,很多人應該跟我一樣預期 xyz() 也應該長出來,好在 cflow 可以輸入多個檔案:
$ cflow *.c輸出結果:
main() <int main (int argc, char **argv) at cflowtest.c:3>: foo() <void foo (void) at foo.c:3>: printf() xyz() <void xyz (void) at xyz.c:3>: printf() bar() <void bar (void) at bar.c:3>: printf() xyz() <void xyz (void) at xyz.c:3>: printf()cflow 預設根節點為 main(),但有時我們只是想觀察某個函數,這時候可以改用:
$ cflow -m foo *.c輸出結果:
foo() <void foo (void) at foo.c:3>: printf() xyz() <void xyz (void) at xyz.c:3>: printf()筆者以前還拿這樣的結果用 PowerPoint 傻傻的畫老半天,現在有 cflow2dot,就不用那麼辛苦了,請先參考官方網站安裝 cflow2dot,接著輸入以下指令:
$ cflow2dot -i *.c -f svg選項 -i 代表輸入檔案,-f 代表輸出格式(此處是 SVG),目錄下會看到 cflow0.svg...cflow3.svg,用瀏覽器打開如下:
有點讓人失望,原本預料他會輸出以下畫面:
筆者試驗了很久沒試出來,按照官網的說明,他應該是一個檔案輸出一個 svg。官網聲稱可以輸出 pdf 然後有 hyper link 可以直接跳到 source code 的對應之處,這部份筆者沒有實驗出來,有哪位先進實驗成功敬請分享,感恩~
其實這樣也算夠用了,畢竟如果把所有的檔案合併輸出成一個超大 svg,那可能會大到瀏覽器無法載入,也大到不知道從何看起。
如果您覺得不夠,接下來的重型武器應該能滿足您
callgraph
callgraph 是對岸泰曉科技發佈到 github 上的幾隻 shell script,功能比起 cflow2dot 簡直有過之而無不及,甚至還有模糊批配這種東西,簡直是霸氣外露,不愧是我大天朝出品。(這幾隻 script 原本的目的是用來分析 Linux Kernel 0.11 版,看起來跟"Linux 內核設計的藝術"這本書有關聯,這本書筆者也有,不過放了很久都沒看,汗顏)。
$ callgraph -f main -d ./選項 -f 代表 call graph 根節點,-d 代表搜尋路徑或檔案,-d 的目的是加快搜尋速度,不然 script 會找出一大堆類似名稱的函數,若檔案很多搜尋速度也會直線下降(所以知道 SSD 的重要性吧?)。輸出結果如下:
Func: main Match: 1 File: 0 All files under ./ 1 ./main.c:int main(int argc, char **argv) Select: 0 ~ 1 ?請選 0(如果選 1,script 只會分析 main.c),然後會得到 main.all.svg,把他打開看看:
這次得到了我們想要的結果。各位,真是太爽拉~~
心得
cflow2dot 可以得到一個 .c 的全景,callgraph 則可以針對某個 function 深入探索。假如您有雙螢幕,其中一個螢幕放上這些圖,不但對您的工作極有助益,也可以顯示您是一位尊爵不凡 的 Professional Programmer,讓您的主管對您讚譽有加(這小子真行)。
不過講正經的,製作 call graph 最主要目的是"大腦超載時代的思考學"一書所強調的「記憶外部化」,如果只靠人腦死背硬記,恐怕 coding 這種工作真如某幸福企業主管講的找剛畢業的就好了。
不過講正經的,製作 call graph 最主要目的是"大腦超載時代的思考學"一書所強調的「記憶外部化」,如果只靠人腦死背硬記,恐怕 coding 這種工作真如某幸福企業主管講的找剛畢業的就好了。
其實類似工具還有比較多人知道的 doxygen,不過跑起來很花時間筆者使用過一次就不用了。如果您能接受 gcc 上打補丁的方式,也可以考慮一下 CodeViz。
不過筆者建議分析程式應該以 call graph 為輔,以 data 為主,也就是 data 在程式中是如何工處理的,資料的流向為何?資料結構產生了哪些變化?很可惜目前還沒找到合適的工具,如果有哪位先進在這方面有經驗,也請不吝分享,謝謝!
沒有留言:
張貼留言