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