我應該怎麼快速掌握 C 語言專案架構 === :::info 今天你在因緣際會下需要研究一份很複雜的程式碼,其複雜的程度大概就是一個正常的開源工具,像是 trace libreoffice 實做等等 你需要怎麼做才能幫助你快速掌握這份程式專案呢? ::: ### 1. 你熟悉專案使用的語言,不過對專案整體架構不甚熟悉 #### 1. doxygen `doxygen` 是一款可以根據設定好的註解型式,自動建立程式架構文件的自由軟體,不少比較 hardcore 的自由軟體文件都是要透過它自動生成的(~~舉例當寫該程式的人不想寫文件的時候~~) :::warning 雖然 `doxygen` 功能已經十分強大,不過其並不支援 trace callback 函式的能力,同時也無法 trace 遞迴函式 這點在 trace 不少 multi-thread 程式(像是 QEMU)時需要小心 ::: #### 2. ncc `ncc` 類似 `gcc` 是一種 C 語言編譯器,不過 `ncc` 更注重提供程式的分析資訊 :::warning 非常可惜的是,`ncc` 相關的中文資訊非常的少(~~而且你通常會查到*國家通訊傳播委員會*~~),而且其用途通常會跟 `codeviz` 下面提到的工具一起使用 ::: #### 3. ctag/ cscope `ctag`/ `cscope` 是以強化 vim 編輯器 debug 的能力,提供像是快速查找 function 對應的定義以及其宣告的位置 :::warning 不過微軟家編輯器 visual studio code 為數眾多的擴充套件都可以幫你作到相同的事 ::: #### 4. codeviz `codeviz` 是結合 `gcc` + `graphviz` 下產出程式碼對應的 call graph,可以圖像化顯示 function 間呼叫的關係 :::warning 不過需要注意的是,`codeviz` 官方網站已經沒有在維護該工具,網路上的文件也偏少且相對較舊;其次為 `codeviz` 僅支援特定版本的 `gcc` ,而其特定版本通常(至少在 Ubuntu平台上需要)自行編譯 `gcc`,編譯過程對新手而言並不是很友善 雖然文件上(雖然網路上有許多文件,但是內容重複度極高)有提到 `ncc` 這款編譯器也可以用來代替 `gcc` 輸出 cdepn 格式檔案,不過文件本身有點語焉不詳 ::: #### 5. cflow `cflow` 是一個相當簡單直白的工具,`cflow` 在找到程式進入點之後會開始印出 function call flow ```shell= $ cflow qemu-img.c ```  同時如果你在看完前面簡略式的程式呼叫之後,想要知道更加詳細的 function call (像是 linker 連結外部的程式碼實做呼叫) 你可以在指令後面多加 include 的函式庫,像是 ```shell= $ cflow qemu-img.c ./*.c ``` (看情況可以導流到外部檔案去,通常這種開源大專案的 call stack 都會很誇張,一個 `qemu-img` 的 function call stack 可以到 12000 行) :::warning 這個功能非常的陽春,不過也是我試到目前最容易成功的,使用最直接的(其他工具的文件都多少有點不齊全) ::: #### 6. `nm` #### 7. `-finstrument-functions` #### 8. `gprof` `gprof` 是類似 `perf` 的效能評估工具,不過與 `perf` 不同的是,`gprof` 需要在編譯流程上更動以獲得更多直觀的分析 * `gprof` 優點在於 *1. 可以自動產出程式碼呼叫對應的 call graph (文字顯示)* *2. 靜態顯示定義到的 function* *3. 分析程式執行期間效能分佈在各函式的情況* :::info 簡單來說,就是結合 `cflow` 與 `perf` (「列出定義到的函式」這個功能有點像 `nm`) ::: * 缺點也是相當明顯 *1. `gprof` 需要在 gcc 編譯時期額外加上 `-pg` 的編譯指令(如果 compile 與 link 分開執行,則兩個指令都需要加上 `-pg`)* :::info 這代表你可能會需要先理解該專案的 `Makefile`,尤其是當 `Makefile` 是由 `cmake` 等自動產生 `makefile` 工具所產生的程式碼時,又或者~~該專案把 `Makefile` 散落在各個模組裡然後名字又取得很奇怪的時候~~;你可能就要先花一段時間 trace `Makefile` 然後才能開始 trace source code …… ::: *2. `gprof` 實做上與 `-fininstrument-functions` 類似,一旦加上 `-pg` 編譯,其每次函式呼叫時會以 `mcount` 作為呼叫的第一個 operation* :::info 事實上有可能因為加入 `-pg` 而導致 `Makefile` 失敗,舉一個實際例子,如果在編譯 QEMU 的 `Makefile` 中加上 `-pg` 的編譯選項,編譯過程會因為 build 部份映像檔找不到 `mcount` 的定義因此編譯失敗(不過這應該是我還不熟其 `Makefile` 的緣故,我以為只要在 `CC` 跟 `LD` 步驟加上 `-pg` 還是太天真了嗎) ::: --- > `gprof` 要怎麼用 #### 9. `record function-call-history` ### 2. 你對專案架構已經有了初步的了解,需要深入研究實做 ### 使用心得 其實真的願意花時間閱讀這些錯誤訊息再動手更改像是 `Makefile` 執行流程 那麼以上出現的 bug 都不算是太大的問題 不過難題在於,會想用 tracing tool 通常都是因為對該程式碼掌握度不足 不了解程式執行流程加上還要為了「準備 tracing」而花費一堆時間 保持著沒有產出沒有進度的狀態實在令人焦慮  ### 參考資料
×
Sign in
Email
Password
Forgot password
or
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.