聊聊關於C/C++調試的看法


只討論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 的步驟

  1. 插入打印語句------如printf、cout等打印語句,能夠顯示程序的動態過程,容易檢查源程序的有關信息;缺點是大量無關數據,發現 bug 有偶然性。
  2. 運行部分程序------爲了測試某段一段可能出錯的代碼,執行整個程序的做法是低效率的;因此應設法讓程序只執行需要檢查的程序段,提高效率。
  3. 藉助調試工具------上面的方法可以說是“人肉debug“,只能在代碼量少的情況下發揮作用。大多數語言有專門的調試工具,藉助工具調試纔是正確的 debug 打開方式。

debug 分類

  1. 靜態調試------插入打印語句printf、cout,輸出寄存器、關鍵變量的動態值。(低效)

  2. 動態調試------即使用調試工具分析程序的動態行爲。如利用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

    顯示程序運行所用的 時間 具體用在什麼操作上,可用於性能優化。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章