基本命令
- 進入GDB:#gdb test
test是要調試的程序,由gcc test.c -g -o test生成。進入后提示符變為(gdb) 。
- 查看源碼:(gdb) l
源碼會進行行號提示。
如果需要查看在其他文件中定義的函數,在l后加上函數名即可定位到這個函數的定義及查看附近的其他源碼。或者:使用斷點或單步運行,到某個函數處使用s進入這個函數。
- 設置斷點:(gdb) b 6
這樣會在運行到源碼第6行時停止,可以查看變量的值、堆棧情況等;這個行號是gdb的行號。
- 查看斷點處情況:(gdb) info b
可以鍵入"info b"來查看斷點處情況,可以設置多個斷點;
運行代碼:(gdb) r
顯示變量值:(gdb) p n
在程序暫停時,鍵入"p 變量名"(print)即可;
GDB在顯示變量值時都會在對應值之前加上 N N",而無需寫冗長的變量名;
- 觀察變量:(gdb) watch n
在某一循環處,往往希望能夠觀察一個變量的變化情況,這時就可以鍵入命令"watch"來觀察變量的變化情況,GDB在"n"設置了觀察點;
單步運行:(gdb) n
程序繼續運行:(gdb) c
使程序繼續往下運行,直到再次遇到斷點或程序結束;
- 退出GDB:(gdb) q
斷點調試
命令格式 | 例子 | 作用 |
---|---|---|
break + 設置斷點的行號 | break n | 在n行處設置斷點 |
tbreak + 行號或函數名 | tbreak n/func | 設置臨時斷點,到達后被自動刪除 |
break + filename + 行號 | break main.c:10 | 用於在指定文件對應行設置斷點 |
break + <0x...> | break 0x3400a | 用於在內存某一位置處暫停 |
break + 行號 + if + 條件 | break 10 if i==3 | 用於設置條件斷點,在循環中使用非常方便 |
info breakpoints/watchpoints [n] | info break | n表示斷點編號,查看斷點/觀察點的情況 |
clear + 要清除的斷點行號 | clear 10 | 用於清除對應行的斷點,要給出斷點的行號,清除時GDB會給出提示 |
delete + 要清除的斷點編號 | delete 3 | 用於清除斷點和自動顯示的表達式的命令,要給出斷點的編號,清除時GDB不會給出任何提示 |
disable/enable + 斷點編號 | disable 3 | 讓所設斷點暫時失效/使能,如果要讓多個編號處的斷點失效/使能,可將編號之間用空格隔開 |
awatch/watch + 變量 | awatch/watch i | 設置一個觀察點,當變量被讀出或寫入時程序被暫停 |
rwatch + 變量 | rwatch i | 設置一個觀察點,當變量被讀出時,程序被暫停 |
catch | 設置捕捉點來補捉程序運行時的一些事件。如:載入共享庫(動態鏈接庫)或是C++的異常 | |
tcatch | 只設置一次捕捉點,當程序停住以后,應點被自動刪除 |
數據命令
命令格式 | 例子 | 作用 |
---|---|---|
display +表達式 | display a | 用於顯示表達式的值,每當程序運行到斷點處都會顯示表達式的值 |
info display | 用於顯示當前所有要顯示值的表達式的情況 | |
delete + display 編號 | delete 3 | 用於刪除一個要顯示值的表達式,被刪除的表達式將不被顯示 |
disable/enable + display 編號 | disable/enable 3 | 使一個要顯示值的表達式暫時失效/使能 |
undisplay + display 編號 | undisplay 3 | 用於結束某個表達式值的顯示 |
whatis + 變量 | whatis i | 顯示某個表達式的數據類型 |
print(p) + 變量/表達式 | p n | 用於打印變量或表達式的值 |
set + 變量 = 變量值 | set i = 3 | 改變程序中某個變量的值 |
- 在使用print命令時,可以對變量按指定格式進行輸出,其命令格式為print /變量名 + 格式,其中常用的變量格式:x:十六進制;d:十進制;u:無符號數;o:八進制;c:字符格式;f:浮點數。
調試運行環境相關命令
命令格式 | 例子 | 作用 |
---|---|---|
set args | set args arg1 arg2 | 設置運行參數 |
show args | show args | 參看運行參數 |
set width + 數目 | set width 70 | 設置GDB的行寬 |
cd + 工作目錄 | cd ../ | 切換工作目錄 |
run | r/run | 程序開始執行 |
step(s) | s | 進入式(會進入到所調用的子函數中)單步執行,進入函數的前提是,此函數被編譯有debug信息 |
next(n) | n | 非進入式(不會進入到所調用的子函數中)單步執行 |
finish | finish | 一直運行到函數返回並打印函數返回時的堆棧地址和返回值及參數值等信息 |
until + 行數 | u 3 | 運行到函數某一行 |
continue(c) | c | 執行到下一個斷點或程序結束 |
return <返回值> | return 5 | 改變程序流程,直接結束當前函數,並將指定值返回 |
call + 函數 | call func | 在當前位置執行所要運行的函數 |
堆棧相關命令
命令格式 | 例子 | 作用 |
---|---|---|
backtrace/bt | bt | 用來打印棧幀指針 |
frame | frame 1 | 用於打印指定棧幀 |
info reg | info reg | 查看寄存器使用情況 |
info stack | info stack | 查看堆棧使用情況 |
up/down | up/down | 跳到上一層/下一層函數 |
backtrace/bt 也可以在該命令后加上要打印的棧幀指針的個數,查看程序執行到此時,是經過哪些函數呼叫的程序,程序“調用堆棧”是當前函數之前的所有已調用函數的列表(包括當前函數)。每個函數及其變量都被分配了一個“幀”,最近調用的函數在 0 號幀中(“底部”幀)
跳轉執行
- jump:指定下一條語句的運行點。可以是文件的行號,可以是file:line格式,可以是+num這種偏移量格式。表式着下一條運行語句從哪里開始。相當於改變了PC寄存器內容,堆棧內容並沒有改變,跨函數跳轉容易發生錯誤。
信號命令
- signal:signal SIGXXX,產生XXX信號,如SIGINT。一種速查Linux查詢信號的方法:# kill -l
運行Shell命令
- 如(gdb)shell ls來運行ls
更多程序運行選項和調試
- 程序運行參數
set args 可指定運行時參數。(如:set args 10 20 30 40 50)
show args 命令可以查看設置好的運行參數。
- 運行環境
path 可設定程序的運行路徑。
show paths 查看程序的運行路徑。
set environment varname [=value] 設置環境變量。如:set env USER=hchen
show environment [varname] 查看環境變量。
- 工作目錄
cd 相當於shell的cd命令。
pwd 顯示當前的所在目錄。
- 程序的輸入輸出
info terminal 顯示你程序用到的終端的模式。
使用重定向控制程序輸出。如:run > outfile
tty命令可以指寫輸入輸出的終端設備。如:tty /dev/ttyb
- 調試已運行的程序
兩種方法:
(1)在UNIX下用ps查看正在運行的程序的PID(進程ID),然后用gdb PID格式掛接正在運行的程序。
(2)先用gdb 關聯上源代碼,並進行gdb,在gdb中用attach命令來掛接進程的PID。並用detach來取消掛接的進程。
- 暫停 / 恢復程
序運行當進程被gdb停住時,你可以使用info program 來查看程序的是否在運行,進程號,被暫停的原因。 在gdb中,我們可以有以下幾種暫停方式:斷點(BreakPoint)、觀察點(WatchPoint)、捕捉點(CatchPoint)、信號(Signals)、線程停止(Thread Stops),如果要恢復程序運行,可以使用c或是continue命令。
- 線程(Thread Stops)
如果程序是多線程,可以定義斷點是否在所有的線程上,或是在某個特定的線程。
break thread
break thread if ...
linespec指定了斷點設置在的源程序的行號。threadno指定了線程的ID,注意,這個ID是GDB分配的,可以通過“info threads”命令來查看正在運行程序中的線程信息。如果不指定thread 則表示斷點設在所有線程上面。還可以為某線程指定斷點條件。如:
(gdb) break frik.c:13 thread 28 if bartab > lim
當你的程序被GDB停住時,所有的運行線程都會被停住。這方便查看運行程序的總體情況。而在你恢復程序運行時,所有的線程也會被恢復運行。
調試core文件
Core Dump:Core的意思是內存,Dump的意思是扔出來,堆出來。開發和使用Unix程序時,有時程序莫名其妙的down了,卻沒有任何的提示(有時候會提示core dumped),這時候可以查看一下有沒有形如core.進程號的文件生成,這個文件便是操作系統把程序down掉時的內存內容扔出來生成的, 它可以做為調試程序的參考
生成Core文件
一般默認情況下,core file的大小被設置為了0,這樣系統就不dump出core file了。修改后才能生成core文件。
#設置core大小為無限
ulimit -c unlimited
#設置文件大小為無限
ulimit unlimited
這些需要有root權限, 在ubuntu下每次重新打開中斷都需要重新輸入上面的第一條命令, 來設置core大小為無限
core文件生成路徑:輸入可執行文件運行命令的同一路徑下。若系統生成的core文件不帶其他任何擴展名稱,則全部命名為core。新的core文件生成將覆蓋原來的core文件。
1)/proc/sys/kernel/core_uses_pid可以控制core文件的文件名中是否添加pid作為擴展。文件內容為1,表示添加pid作為擴展名,生成的core文件格式為core.xxxx;為0則表示生成的core文件同一命名為core。
可通過以下命令修改此文件:
echo "1" > /proc/sys/kernel/core_uses_pid
2)proc/sys/kernel/core_pattern可以控制core文件保存位置和文件名格式。
可通過以下命令修改此文件:
echo "/corefile/core-%e-%p-%t" > core_pattern,可以將core文件統一生成到/corefile目錄下,產生的文件名為core-命令名-pid-時間戳
以下是參數列表:
%p - insert pid into filename 添加pid
%u - insert current uid into filename 添加當前uid
%g - insert current gid into filename 添加當前gid
%s - insert signal that caused the coredump into the filename 添加導致產生core的信號
%t - insert UNIX time that the coredump occurred into filename 添加core文件生成時的unix時間
%h - insert hostname where the coredump happened into filename 添加主機名
%e - insert coredumping executable name into filename 添加命令名
- 用gdb查看core文件
發生core dump之后, 用gdb進行查看core文件的內容, 以定位文件中引發core dump的行.
gdb [exec file] [core file]
如:
gdb ./test core
或gdb ./a.out
core-file core.xxxx
gdb后, 用bt命令backtrace或where查看程序運行到哪里, 來定位core dump的文件->行.
待調試的可執行文件,在編譯的時候需要加-g,core文件才能正常顯示出錯信息
1)gdb -core=core.xxxx
file ./a.out
bt
2)gdb -c core.xxxx
file ./a.out
bt
- 用gdb實時觀察某進程crash信息
啟動進程
gdb -p PID
c
運行進程至crash
gdb會顯示crash信息
bt