GDB (The GNU Project Debugger)是 Linux 系統下調試 C 和 C++ 程序的主要神兵。Vim教程網(https://vimjc.com)介紹多種方式下使用 GDB 啟動進程調試的方法和命令。
要使得 C 和 C++ 程序能在 GDB 下正常進行調試,必須在程序編譯期間把基本的調試信息(如變量名、函數名、函數調用堆棧等)添加到可執行文件中。gcc、cc、g++ 等編譯器可通過編譯參數 -g
指定添加調試信息。
當使用 GDB 加載不包含調試信息的二進制文件或進程時,GDB終端會提示錯誤信息:”no debugging symbols found”。
一、GDB調試未執行程序
對於本地的某個二進制文件 demo ( GDB 也支持遠程調試),若其啟動時不需要命令行參數,則可以在shell下使用命令 gdb demo
進入 GDB,並輸入 run
(縮寫形式 r
) 啟動對demo的調試。
若 demo 程序啟動時需要命令行參數,則可以在使用 gdb demo
命令進入 GDB 后,使用命令 run arg1 arg2...
提供命令行參數並啟動對 demo 程序的調試。
二、GDB調試運行中程序
使用 GDB 調試正在運行的程序時,必須先找到該程序運行在操作系統中的進程號 (PID)。可以使用 Linux 命令 ps ef | grep -w demo
、 ps aux | grep -w demo
或 pidof demo
獲取到 demo 進程當前的進程號。
獲取到待調試的目標進程號后 (假設為 pid ),可以使用 gdb
命令進入 GDB 終端,並使用 attach pid
的方式啟動對當前正在運行的 demo 進程的 GDB 調試。
也可以使用 gdb -p pid
命令直接進入 GDB 並啟動對該進程的調試。
對於使用多線程模式的進程,可以在 GDB 中使用 info threads
命令顯示當前進程中所有線程的基本調試信息,包括:GDB 分配的線程ID、線程堆棧等。線程列表中,GDB 線程 ID 左側的 * 表示當前真正被調試的線程。
可通過 thread tid
命令切換和啟動對 GDB 線程號為 tid 的線程進行調試。關於使用 GDB 調試多進程和多線程,后續會有獨立的文章進行詳細介紹。
三、GDB調試core文件
當程序在 Linux 系統下發生異常崩潰(如段錯誤)時,內核會將該應用程序在崩潰發生時的內存數據、程序調用堆棧等核心信息轉存到磁盤,這種功能稱之為 core dump,中文可翻譯為 核心轉儲。
core dump 是程序異常退出時的內存快照,是異常發生后對程序進行現場還原和故障排查的關鍵線索。Linux 進程 core 掉可以說是所有 C 和 C++ 程序員接觸最頻繁而又最不想碰到的問題。
可通過 ulimit -c
查看和指定 core 文件的大小,通過修改 /proc/sys/kernel/core_pattern
文件可指定 core 文件保存在本地磁盤中的路徑和文件名格式。
GDB 對 core 文件的分析和調試提供了非常強大的功能支持,可使用 gdb demo/data/core/xxx
啟動對 demo 進程某次產生的core文件 /data/core/xxx
的分析和調試,也可以使用 gdb -c /data/core/xxx
加載和分析 core 文件。
GDB 正常加載 core 文件后,便可以使用 backtrace
(縮寫形式 bt
) 顯示程序異常退出時刻的函數堆棧情況,再使用 frame
、 print
、 up
、 down
、 where
等命令對異常現場進行詳細分析。
為了讓程序產生 dump ,將 demo.cpp 中的輸出語句 printf("%s: %d\n",(char*)ptr,array[i]);
改成 printf("%s: %s\n",(char*)ptr,array[i]);
后在編譯時加入 -w
參數忽略掉警告后重新生成 demo 可執行文件。
關於 GDB 調試程序和 core 文件的具體方法和命令,請關注Vim教程網(https://vimjc.com)后續 GDB 系列的后續文章。
PS:使用 quit
(縮寫形式 q
) 可退出 GDB。
轉自:https://vimjc.com/debug-program-with-gdb.html