只討論
Linux
環境下的 C/C++ debug
。
在 Windows 環境下開發由很多優秀的 IDE 可以使用,而在 Linux 下開發C/C++,最好的開發環境並不是 IDE,而是一系列工具的組合。不要執着於爭論到底是 ide 齊全還是 vim/emacs 效率高,只要用慣、用熟了,效率不會區別太大。確實存在某些場合只能使用 vim ,但這樣並不能說明哪種更好。嗯……習慣、喜歡。
當然,vim 等一開始需要花點時間折騰,需要耐心和興趣,不過維護好自己的vimrc
等配置文件,之後在使用上如何就見仁見智了。
步驟 | 工具 |
---|---|
編輯 | vim/emacs/vscode + plugins |
調試 | gdb / log /valgrind / cppcheck / file / nm / ldd 等 |
編譯 | gcc / g++/ cmake / makefile / clang 等 |
鏈接 | link |
遠程調試 | gdb-server / ssh? |
腳本 | shell |
分屏 | tmux |
debug 是什麼
調試,是一種發現源代碼錯誤,排查 Bug 的過程,錯誤的類型有語法錯誤,邏輯錯誤,內存泄露等。
debug 的步驟
- 插入打印語句------如
printf、cout
等打印語句,能夠顯示程序的動態過程,容易檢查源程序的有關信息;缺點是大量無關數據,發現 bug 有偶然性。 - 運行部分程序------爲了測試某段一段可能出錯的代碼,執行整個程序的做法是低效率的;因此應設法讓程序只執行需要檢查的程序段,提高效率。
- 藉助調試工具------上面的方法可以說是“人肉debug“,只能在代碼量少的情況下發揮作用。大多數語言有專門的調試工具,藉助工具調試纔是正確的 debug 打開方式。
debug 分類
-
靜態調試------插入打印語句
printf、cout
,輸出寄存器、關鍵變量的動態值。(低效) -
動態調試------即使用調試工具分析程序的動態行爲。如利用
valgrind
檢查內存泄露問題;設置斷點
(程序語言自身提供,不是外部工具),分析程序此時的狀態;使用內置的宏
。-
使用調試標記
在源代碼中使用相應的輔助代碼,debug 完成之後 隱藏 這些代碼的一種調試策略。藉助
#define/#ifdef/#endif
三個編譯指令。相當於使用#define
定義宏,#ifdef / #endif
之間包含調試代碼。調試完成後,生成發行版時,在編譯器命令行參數中設置不提供調試標記,這段代碼就會銷燬。常用調試標記_DEBUG(VC++)
#ifdef _DEBUG std::cout << "something..." << std::endl; #endif
-
使用調試變量
運行時設置一個
bool
類型的變量,決定特定調試程序段的開關,且該變量可以通過命令行參數設定。#include ... bool _debug_; int main(int argc, char* argv[]) { if(_debug_){ //do something } }
-
使用內置宏
__FILE__ / __FUNCTION__ / __LINE__
自動獲取有關模塊、函數、宏的信息。{ std::cout << __FILE__ << std::endl; std::cout << __FUNTION__ << std::endl; std::cout << __LINE__ << std::endl; }
-
debug 調試跟蹤工具
-
gdb ==> 最重要最常用最基礎(Linux)
- 設置斷點,且斷點可以是條件表達式
- 快速定位 bug,如使用
bt
/where
可以快速找到程序出現core dump
(核心轉儲)的位置。core dump
就是程序運行中發生execption
,異常退出時,由操作系統把程序當前的內存狀況存儲在一個core文件
中,又叫做segmentation fault。
-
valgrind ==> 內存
- 內存調試、內存泄漏檢測以及性能分析
-
strace
- 跟蹤並顯示用戶程序中的系統調用的詳細信息
(parameters/return values/system call/time/…)
- 適用於
a.out/.exe
或運行中的進程,用戶可觀察程序的運行狀態
- 跟蹤並顯示用戶程序中的系統調用的詳細信息
-
pstack
查看進程的實時堆棧信息。
靜態分析工具
-
cppcheck
- C/C++代碼缺陷靜態檢查,檢測未使用的變量,越界訪問,內存泄漏等問題。
- 不同於其他編譯器和分析工具,
cppcheck
只檢查編譯器檢查不出來的bug,不檢查語法錯誤。作爲編譯器的一種補充檢查。
-
ldd
ldd
命令可以查看當前a.out/.exe
或者動態庫需要依賴那些動態庫,以及缺少哪些動態庫。ldd -r
可以報告缺少的目標對象和函數。 -
file
查看文件類型,對於可執行文件或動態庫,可查看使用需要 link 動態庫,同時可查看是否包含符號表。
file filename
-
nm
列出目標文件中的符號。通常情況下,對於鏈接問題可以通過該命令的
-D -u
參數來查看相關符號。nm -CDu filename
-
strip
清理共享庫或可執行文件中的符號信息和調試信息,通常在程序發佈前使用。
性能調試工具
-
perf ==> CPU
分析應用程序或內核代碼性能。對單個程序做函數調用次數、上下文切換次數、中斷次數等信息進行統計。
-
prof/gprof
顯示程序運行所用的 時間 具體用在什麼操作上,可用於性能優化。