GDB使用总结
經典編譯參數:
# cc? -g? -o?? xx? xx.c
?或者
# cc xx.c? -g -o xx
?
如果調試不是進程總的程序
可以直接
#gdb? 程序名即可
# i???? 打印行號
#break?? 行號
#r????????? 重新開始調試
利用set args 命令就可以修改發送給程序的參數,而使用show args 命令就可以查看其缺省參數的列表。
(gdb) set args –b –x
(gdb) show args
可以先-p上程序 再加參數。
?
給GDB傳遞參數
int main( int argc, char* argv[] )
if( argc <= 2 )?{
??????? printf( "usage: %s ip_address port_number\n", basename( argv[0] ) );
??????? return 1;
?}
const char* ip =argv[1];
int port = atoi( argv[2] );
#ps aux 查進程
#gdb -p pid??? 注意千萬不要在這后增加參數 沒用的
#set args? localhost 7777
#break main
#r
#s
?
二:編譯選項
要使用gdb調試必須使用-g編譯選項,同時還要啟用O0,避免O2優化。
方法一:
# ./configure CFLAGS="-g -O0" --prefix=/usr/local/xxx
方法二:
# make CFLAGS="-g -O0"
方法三:
直接修改Makefile文件的的CFLAGS選項,例如nginx的Makefile
CFLAGS =? -pipe? -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Werror -g
注意:如果已經生成這樣的Makefile文件以后,如果繼續使用# make CFLAGS="-g -O0"?? 那么編譯的時候就會
cc -c -g -g -O0?
可見make 后的CFLAGS是拼在MakeFile文件的CFLAGS后的,避免重復-g? 可以? make CFLAGS="-O0"
但是,這樣做顯得多余,完全可以一步到位。
?
查看宏定義
注意:Nginx中有大量的宏,如果不做特殊處理是看不到這些宏定義的:
?
必須編譯的時候使用ggdb3才可以查看定義。
修改auto/cc/conf文件
ngx_compile_opt="-c"
變為
ngx_compile_opt="-c -ggdb3"
或者
#make?CFLAGS="-ggdb3?-O0"?
#info macro NGX_OK
#macro expand NGX_OK
?
查看ngx_core.h
??
三:列文件
1. List
(gdb) list line1,line2
list
輸出從上次調用list命令開始往后的10行程序代碼。
list -
輸出從上次調用list命令開始往前的10行程序代碼。
list n
輸出第n行附近的10行程序代碼。
list function
輸出函數function前后的10行程序代碼。
?????????????? list n,m
????????????????????? 輸出n行后的m行
四:執行程序
要想運行準備調試的程序,可使用run命令,在它后面可以跟隨發給該程序的任何參數,包括標準輸入和標準輸出說明符(<和>)和外殼通配符(*、?、[、])在內。
如果你使用不帶參數的run命令,gdb就再次使用你給予前一條run命令的參數,這是很有用的。
利用set args 命令就可以修改發送給程序的參數,而使用show args 命令就可以查看其缺省參數的列表。
(gdb) set args –b –x
(gdb) show args
backtrace命令為堆棧提供向后跟蹤功能。
Backtrace 命令產生一張列表,包含著從最近的過程開始的所以有效過程和調用這些過程的參數。
顯示當前函數調用關系?
(gdb) bt??
?
五:顯示數據
利用print 命令可以檢查各個變量的值。
(gdb) print p (p為變量名)
whatis 命令可以顯示某個變量的類型
(gdb) whatis p
type = int *
print 是gdb的一個功能很強的命令,利用它可以顯示被調試的語言中任何有效的表達式。表達式除了包含你程序中的變量外,還可以包含以下內容:
l 對程序中函數的調用
(gdb) print find_entry(1,0)
l 數據結構和其他復雜對象
(gdb) print *table_start
$8={e=reference=’\000’,location=0x0,next=0x0}
l 值的歷史成分
(gdb)print $1 ($1為歷史記錄變量,在以后可以直接引用 $1 的值)
l 人為數組
人為數組提供了一種去顯示存儲器塊(數組節或動態分配的存儲區)內容的方法。早期的調試程序沒有很好的方法將任意的指針換成一個數組。就像對待參數一樣,讓我們查看內存中在變量h后面的10個整數,一個動態數組的語法如下所示:
base@length
因此,要想顯示在h后面的10個元素,可以使用h@10:
(gdb)print h@10
$13=(-1,345,23,-234,0,0,0,98,345,10)
?
六:斷點(breakpoint)
break命令(可以簡寫為b)可以用來在調試的程序中設置斷點,該命令有如下四種形式:
l break line-number 使程序恰好在執行給定行之前停止。
l break function-name 使程序恰好在進入指定的函數之前停止。
l break line-or-function if condition 如果condition(條件)是真,程序到達指定行或函數時停止。
l break routine-name 在指定例程的入口處設置斷點
如果該程序是由很多原文件構成的,你可以在各個原文件中設置斷點,而不是在當前的原文件中設置斷點,其方法如下:
(gdb) break filename:line-number
(gdb) break filename:function-name
要想設置一個條件斷點,可以利用break if命令,如下所示:
(gdb) break line-or-function if expr
例:
(gdb) break 46 if testsize==100
從斷點繼續運行:countinue 命令
?
七.斷點的管理
1. 顯示當前gdb的斷點信息:
(gdb) info break
他會以如下的形式顯示所有的斷點信息:
Num Type Disp Enb Address What
1 breakpoint keep y 0x000028bc in init_random at qsort2.c:155
2 breakpoint keep y 0x0000291c in init_organ at qsort2.c:168
(gdb)
2.刪除指定的某個斷點:
(gdb) delete breakpoint 1
該命令將會刪除編號為1的斷點,如果不帶編號參數,將刪除所有的斷點
(gdb) delete breakpoint
3.禁止使用某個斷點
(gdb) disable breakpoint 1
該命令將禁止斷點 1,同時斷點信息的 (Enb)域將變為 n
4.允許使用某個斷點
(gdb) enable breakpoint 1
該命令將允許斷點 1,同時斷點信息的 (Enb)域將變為 y
5.清除原文件中某一代碼行上的所有斷點
(gdb)clean number
注:number 為原文件的某個代碼行的行號
八.變量的檢查和賦值
l whatis:識別數組或變量的類型
l ptype:比whatis的功能更強,他可以提供一個結構的定義
l set variable:將值賦予變量
l print 除了顯示一個變量的值外,還可以用來賦值
?
九:單步執行
next
不進入的單步執行
step
進入的單步執行
?
跳出函數
如果已經進入了某函數,而想退出該函數返回到它的調用函數中,可使用命令
finish
十:函數的調用
l call name 調用和執行一個函數
(gdb) call gen_and_sork( 1234,1,0 )
(gdb) call printf(“abcd”)
$1=4
l finish 結束執行當前函數,顯示其返回值(如果有的話)
?
十一:進入子進程
1.set follow-fork-mode <parent/child>??
?
十二:命令的歷史
為了允許使用歷史命令,可使用 set history expansion on 命令
(gdb) set history expansion on
小結:常用的gdb命令
backtrace 顯示程序中的當前位置和表示如何到達當前位置的棧跟蹤(同義詞:where)
breakpoint 在程序中設置一個斷點
cd 改變當前工作目錄
clear 刪除剛才停止處的斷點
commands 命中斷點時,列出將要執行的命令
continue 從斷點開始繼續執行
delete 刪除一個斷點或監測點;也可與其他命令一起使用
display 程序停止時顯示變量和表達時
down 下移棧幀,使得另一個函數成為當前函數
frame 選擇下一條continue命令的幀
info 顯示與該程序有關的各種信息
jump 在源程序中的另一點開始運行
kill 異常終止在gdb 控制下運行的程序
list 列出相應于正在執行的程序的原文件內容
next 執行下一個源程序行,從而執行其整體中的一個函數
print 顯示變量或表達式的值
pwd 顯示當前工作目錄
pype 顯示一個數據結構(如一個結構或C++類)的內容
quit 退出gdb
reverse-search 在源文件中反向搜索正規表達式
run 執行該程序
search 在源文件中搜索正規表達式
set variable 給變量賦值
signal 將一個信號發送到正在運行的進程
step 執行下一個源程序行,必要時進入下一個函數
undisplay display命令的反命令,不要顯示表達式
until 結束當前循環
up 上移棧幀,使另一函數成為當前函數
watch 在程序中設置一個監測點(即數據斷點)
whatis 顯示變量或函數類型
****************************************************
GNU的調試器稱為gdb,該程序是一個交互式工具,工作在字符模式。在 X Window 系統中,有一個gdb的前端圖形工具,稱為xxgdb。gdb 是功能強大的調試程序,可完成如下的調試任務:
* 設置斷點;
* 監視程序變量的值;
* 程序的單步執行;
* 修改變量的值。
在可以使用 gdb 調試程序之前,必須使用 -g 選項編譯源文件。可在 makefile 中如下定義 CFLAGS 變量:
CFLAGS = -g
運行 gdb 調試程序時通常使用如下的命令:
gdb progname
在 gdb 提示符處鍵入help,將列出命令的分類,主要的分類有:
* aliases:命令別名
* breakpoints:斷點定義;
* data:數據查看;
* files:指定并查看文件;
* internals:維護命令;
* running:程序執行;
* stack:調用棧查看;
* statu:狀態查看;
* tracepoints:跟蹤程序執行。
鍵入 help 后跟命令的分類名,可獲得該類命令的詳細清單。
?
GDB實戰
?
設置條件斷點
#include <stdio.h>
int main()
{int i;int a=0;for(i=0; i<10; i++){a++;printf("i=%d\n",a);printf("a=%d\n",a);}
}
?
awatch 變量或表達式
當表達式的值發生改變或表達式的值被讀取時,程序就會停止運行。
* watch :與awatch類似用來設置觀察點,但程序只有當表達式的值發生改變時才會停止運行。使用格 式:
watch 變量或表達式
需要注意的是,awatch和watch都必須在程序運行的過程中設置觀察點,即可運行run之后才能設置。
?
awatch:
watch:
?
-----------------------------------
內核轉儲
generate-core-file可將調試中的進程生成內核轉儲文件
gcore可以從命令行直接生成內核轉儲文件,該命令無需停止正運行的程序以獲得內核轉儲文件
(gdb) generate-core-file
Saved corefile core.2785
(gdb) gcore 'ps'
Saved corefile 'ps'
小技巧:
當前工作目錄
(gdb) pwd
Working directory /root.
------------------------------------
擴展閱讀:
GDB 格式化結構體輸出?
Linux環境Nginx安裝與調試
?
更多參考:
在Emacs中使用gdb調試程序
利用emacs調試C++程序教程
Emacs+GDB遠程調試ARM-LINUX程序
用GDB調試程序
總結
- 上一篇: 深度分析typedef--定义自己的数据
- 下一篇: Nginx模块开发