目錄
前文列表
《程序編譯流程與 GCC 編譯器》
《C 語言編程 — 基本語法》
《C 語言編程 — 基本數據類型》
《C 語言編程 — 變量與常量》
《C 語言編程 — 運算符》
《C 語言編程 — 邏輯控制語句》
《C 語言編程 — 函數》
《C 語言編程 — 高級數據類型 — 指針》
《C 語言編程 — 高級數據類型 — 數組》
《C 語言編程 — 高級數據類型 — 字符串》
《C 語言編程 — 高級數據類型 — 枚舉》
《C 語言編程 — 高級數據類型 — 結構體與位域》
《C 語言編程 — 高級數據類型 — 共用體》
《C 語言編程 — 高級數據類型 — void 類型》
《C 語言編程 — 數據類型的別名》
《C 語言編程 — 數據類型轉換》
《C 語言編程 — 宏定義與預處理器指令》
《C 語言編程 — 異常處理》
《C 語言編程 — 頭文件》
《C 語言編程 — 輸入/輸出與文件操作》
《C 語言編程 — 堆棧與內存管理》
《C 語言編程 — 指令行參數》
代碼調試
- 斷點:所謂斷點(BreakPoint),可以理解為障礙物,人遇到障礙物不能行走,程序遇到斷點就暫停執行。
- 逐語句調試:逐語句,就是每次執行一行語句,如果碰到函數調用,它就會進入到函數里面。
- 逐過程調試:逐過程,碰到函數時,不進入函數,把函數調用當成一條語句執行。
- 跳出當前執行過程:跳出,是當你進入到函數內,跳出可以讓你直接執行函數內剩余的語句,直到返回到該函數被調用時的后面的語句處。
- 監視窗口:程序執行完某條語句時,使用監視窗口可以查看程序中變量的具體內容、程序中的內存狀態、程序中的寄存器狀態等。
GDB
GDB(GNU Debugger)包含在 GNU 的 GCC 開發套件中,是基於命令行的、功能強大的程序調試工具。對於一名 Linux 平台下工作的 C/C++ 程序員,GDB 是必不可少的工具。
安裝:
yum install gdb -y
GDB 主要能夠幫忙我們完成下面四個方面的功能:
- 可以按照自定義的要求運行程序。
- 支持基於條件表達式的斷點。
- 當程序被停住時,可以檢查此時程序中所發生的事情。
- 動態的修改程序的執行環境。
程序的調試過程主要有:單步執行,跳入函數,跳出函數,設置斷點,設置觀察點,查看變量。
簡單示例:
$gdb programmer # 啟動 gdb
>break main # 設置斷點
>run # 運行調試程序
>next # 單步調試
>print var1 # 打印變量值
>list # 顯示當前調試處的源代碼
>info b # 顯示當前斷點設置情況
啟動 GDB
對 C/C++ 程序的調試,需要在編譯前就加上 -g 選項。-g 選項的作用是在可執行文件中加入源文件信息,所以在調試時必須保證 gdb 能找到源文件。不使用 -g 的話將看不見程序的函數名和變量名,代替它們的全是運行時的內存地址。
- DEBUG 模式編譯
$ gcc -g main.c -o main
- 調試執行文件:
$ gdb main
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-115.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/main...done.
(gdb)
NOTE:如果沒有加 -g 進行編譯的話,會出現錯誤。意思是沒能從可執行文件中獲得符號表(symbol table)信息,你可以使用 -se file 指令,從指定文件中讀取符號表信息,並把它用在可執行文件中。
No symbol table is loaded. Use the "file" command.
- 調試服務程序:GDB 也可以用於調試服務程序,可以指定服務程序運行時的進程 ID。GBD 會自動 Attach 上去,並開啟調試。此時,程序的執行文件應該已經被加入到 PATH 環境變量中。
$ gdb <program> <PID>
交互命令
啟動了 GDB 后,就進入到指令行的交互模式,可以通過以下指令完成對程序的調試。
運行程序
- run [arglist](r)運行程序:當遇到斷點后,程序會在斷點處停止運行,等待用戶輸入下一步的命令。如果指定了 arglist,則作為參數運行程序。
- set var 變量名=變量值:設置運行時參數。
- continue(c)繼續執行:到下一個斷點處(或運行結束)。
- next(n)單步執行:當遇到函數調用時,不會進入函數體。
- step(s)單步執行:當遇到函數調用時,則進入函數。與 next 的主要區別是,step 遇到自定義函數后,會步進到函數中運行,而 next 則直接調用函數,不會進入到函數體內。
- until:當你厭倦了在一個循環體內單步執行時,這個命令可以運行程序直到退出循環體。
- until n:運行至 n 行,不僅僅用來跳出循環。
- return:強制從當前函數返回。
- finish:運行程序,直到當前函數完成返回,並打印函數返回時的堆棧地址和返回值及參數值等信息。
- call 函數(參數):調用有效函數,並傳入實參,如:
call gdb_test(55)
。 - Ctrl-C:在當前位置停止執行正在執行的程序,斷點在當前行。
- quit(q):退出 GDB 調試終端。
- shell:使你能不離開 gdb 就執行 UNIX shell 命令。
暫停程序
在 GDB 中,程序有以下幾種暫停方式:
- 斷點(BreakPoint)
- 觀察點(WatchPoint)
- 捕捉點(CatchPoint)
- 信號(Signals)
- 線程停止(Thread Stops)
當已定義好的停止點沒有用時,可以使用 delete、clear、disable、enable 這幾個命令來進行維護。此外還有 ignore,可以指定程序運行時,忽略停止條件幾次。
設置斷點
- break linenum(b n):在第 n 行處設置斷點。
- break [file:]function、break [file:]linenum:在指定源文件的指定函數或行號設置斷點,e.g.
b OAGUPDATE.cpp:578
。 - b fn1 if a>b:設置條件斷點。
- txbreak:在當前函數的退出的點上設置一個臨時的斷點,只可使用一次。
- info b :顯示當前程序的斷點設置情況。
- delete n:刪除第 n 個斷點。
- enable n:開啟第 n 個斷點。
- clear n:清除第 n 行的斷點。
- delete breakpoints:清除所有斷點。
設置觀察點
觀察點通常用來觀察某個表達式的值是否變化了。如果有變化,馬上停住程序。
- watch:設置一個監視點,一旦被監視的表達式的數值改變了,停住程序。
- rwatch:當表達式被讀時,停住程序。
- awatch:當表達式的值被讀或被寫時,停住程序。
- info watchpoints:列出當前設置的所有觀察點。
設置捕捉點
設置捕捉點來補捉程序運行時的一些事件,e.g. 載入共享庫(動態鏈接庫)或是 C++ 的異常。
- catch:當時間發生時,停住程序。
- tcatch:只生效一次的捕捉點。
Event 列表:
打印信息
- list [linenum]/[function](l n/func):列出程序的源代碼,默認每次顯示 10 行。重復執行則輸出下邊的內容。
- print(p):打印當前程序所有的有效表達式。
- print func(x):將實參 x 傳入並調用 func 函數。x 可以使一個數值,也可以是一個有效變量。
- ptype:顯示變量的類型。
- display:在單步運行時非常有用,設置了一個表達式后,將在每次單步執行時,緊接着輸出被設置的表達式及值。
- display list:查看 display 索引。
- undisplay:刪除一個 display 設置的變量顯示。
- whatis :查詢變量或函數。
- info func: 查詢函數。
- info locals:顯示當前堆棧頁的所有變量。
- bt:Backtrace,顯示程序堆棧信息。
查詢運行信息
- where/bt:當前運行的堆棧列表。
- bt backtrace:顯示當前調用堆棧。
- up/down:改變堆棧顯示的深度。
- set args:指定運行時的參數。
- show args:查看設置好的參數。
- info program:查看程序的是否在運行,進程號,被暫停的原因。
分割窗口
- layout:分割窗口。
- layout src:顯示源代碼窗口。
- layout asm:顯示反匯編窗口。
- layout regs:顯示源代碼、反匯編、CPU 寄存器窗口。
- layout split:顯示源代碼、反匯編窗口。
- Ctrl + L:刷新窗口。