使用gdb调试程序详解
熟練使用gdb是一個linux下開發人員必備的一項技能,我們由淺入深的學習一下gdb的強大功能。
一.gdb簡單介紹
名稱
提要
????????[-tty=dev] [-s symfile] [-e prog] [-se prog] [-c
????????core] [-x cmds] [-d dir] [prog[core|procID]]
描述
??? 調試器(如GDB)的目的是允許你在程序運行時進入到某個程序內部去看看該程序在做什么,或者在該程序崩潰時它在做什么。
GDB主要可以做4大類事(加上一些其他的輔助工作),以幫助用戶在程序運行過程中發現bug。
??? o? 啟動您的程序,并列出可能會影響它運行的一些信息
??? o? 使您的程序在特定條件下停止下來
??? o? 當程序停下來的時候,檢查發生了什么(簡單來說,就是當在打開了core文件限制后,gdb能夠調試core文件來定位程序出現問題的地方)
??? o? 對程序做出相應的調整,這樣您就能嘗試糾正一個錯誤并繼續發現其它錯誤
二.gdb的啟動
一般來說GDB主要調試的是C/C++的程序。要調試C/C++的程序,首先 在編譯時,我們必須要把調試信息加到可執行文件中。使用編譯器( cc/gcc/g++)的 -g 參數可以做到這一點。如:
g++ -g hello.cpp-o hello
如果沒有-g,你將看不見程序的函數名、變量名,所代替的全是運行 時的內存地址。
啟動GDB的方法有以下幾種:
????2、gdb <program> core 用gdb同時調試一個運行程序和core文件,core是程序非法執行后core dump后產生的文件。
????3、gdb <program><PID> 如果你的程序是一個服務程序,那么你可以指定這個服務程序運行時 的進程ID。gdb會自動attach上去,并調試他。program應該在PATH環 境變量中搜索得到。
GDB啟動時,可以加上一些GDB的啟動開關,詳細的開關可以用gdb -help查看。我在下面只例舉一些比較常用的參數:
??????列出所有選項,并附簡要說明。
-symbols=file (-s file)
??????讀出文件(file)中的符號表。
-write
??????開通(enable)往可執行文件和核心文件寫的權限。
-exec=file (-e file)
??????在適當時候把File作為可執行的文件執行,來檢測與core dump結合的數據。
-se File
??????從File讀取符號表并把它作為可執行文件。
-core File (-c File)
??????把File作為core dump來執行。
-directory=Directory (-d Directory)
??????把Dicrctory加入源文件搜索的路徑中。
-cd=Directory
??????運行GDB,使用Directory作為它的工作目錄,取代當前工作目錄.
三.gdb的命令字介紹
我們簡要介紹一下在gdb調試中需要用到的命令字
??????裝入想要調試的可執行文件
kill [filename]
??????終止正在調試的程序
break [file:]function
??????在(file文件的)function函數中設置一個斷點
clear
??????刪除一個斷點,這個命令需要指定代碼行或者函數名作為參數
run [arglist]
??????運行您的程序 (如果指定了arglist,則將arglist作為參數運行程序)
bt Backtrace
??????顯示程序堆棧信息
print expr
??????打印表達式的值
continue
??????繼續運行您的程序 (在停止之后,比如在一個斷點之后)
list
??????列出產生執行文件的源代碼的一部分
next
??????單步執行 (在停止之后); 跳過函數調用(與step相對應,step會進入函數內部)
nexti
??????執行下一行的源代碼中的一條匯編指令
set
??????設置變量的值。例如:set nval=54 將把54保存到nval變量中;設置輸入參數也可以通過這個命令(例如當三個入參分別為a、b、c的話,set args a b c)
step
??????單步執行 (在停止之后); 進入函數調用
stepi
??????繼續執行程序下一行源代碼中的匯編指令。如果是函數調用,這個命令將進入函數的內部,單步執行函數中的匯編代碼
watch
??????使你能監視一個變量的值而不管它何時被改變
rwatch
??????指定一個變量,如果這個變量被讀,則暫停程序運行,在調試器中顯示信息,并等待下一個調試命令。參考rwatch和watch命令
awatch
??????指定一個變量,如果這個變量被讀或者被寫,則暫停程序運行,在調試器中顯示信息,并等待下一個調試命令。參考rwatch和watch命令
Ctrl-C
??????在當前位置停止執行正在執行的程序,斷點在當前行
disable
??????禁止斷點功能,這個命令需要禁止的斷點在斷點列表索引值作為參數
display
??????在斷點的停止的地方,顯示指定的表達式的值。(顯示變量)
undisplay
??????刪除一個display設置的變量顯示。這個命令需要將display list中的索引做參數
enable
??????允許斷點功能,這個命令需要允許的斷點在斷點列表索引值作為參數
finish
??????繼續執行,直到當前函數返回
ignore
??????忽略某個斷點制定的次數。例:ignore 4 23 忽略斷點4的23次運行,在第24次的時候中斷
info [name]
??????查看name信息
load
??????動態載入一個可執行文件到調試器
xbreak
??????在當前函數的退出的點上設置一個斷點
whatis
??????顯示變量的值和類型
ptype
??????顯示變量的類型
return
??????強制從當前函數返回
txbreak
??????在當前函數的退出的點上設置一個臨時的斷點(只可使用一次)
make
??????使你能不退出 gdb 就可以重新產生可執行文件
shell
??????使你能不離開 gdb 就執行 UNIX shell 命令
help [name]
??????顯示GDB命令的信息,或者顯示如何使用GDB的總體信息
quit
??????退出gdb.
四.gdb調試程序實例
源程序:tst.c
int func(int n)
{
????int sum=0,i;
????for(i=0; i<n; i++)
????{
????????sum+=i;
????}
????return sum;
}
void main()
{
????int i; long result = 0;
????for(i=1; i<=100; i++)
????{
????????result += i;
????}
????printf("result[1-100] = %d \n", result );
????printf("result[1-250] = %d \n", func(250) );
}
編譯生成執行文件:(Linux下)
使用GDB調試:
hchen/test>gdb tst<---------- 啟動GDBGNU gdb 5.1.1
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type"show warranty"for details.
This GDB was configured as "i386-suse-linux"...
(gdb) l <-------------------- l命令相當于list,從第一行開始例出原碼。
1 #include<stdio.h>
2
3 int func(int n)
4 {
5 int sum=0,i;
6 for(i=0; i<n; i++)
7 {
8 sum+=i;
9 }
10 return sum;
(gdb) <-------------------- 直接回車表示,重復上一次命令
11 }
12
13
14 main()
15 {
16 int i;
17 long result=0;
18 for(i=1; i<=100; i++)
19 {
20 result += i;
(gdb) break 16 <-------------------- 設置斷點,在源程序第16行處。
Breakpoint 1 at 0x8048496: file tst.c, line16.
(gdb) break func <-------------------- 設置斷點,在函數func()入口處。
Breakpoint 2 at 0x8048456: file tst.c, line5.
(gdb) info break <-------------------- 查看斷點信息。
Num Type Disp Enb Address What
1 breakpoint keep y 0x08048496 in main at tst.c:16
2 breakpoint keep y 0x08048456 in func at tst.c:5
(gdb) r <--------------------- 運行程序,run命令簡寫
Starting program: /home/hchen/test/tst
Breakpoint 1, main () at tst.c:17<---------- 在斷點處停住。
17 long result=0;
(gdb) n <--------------------- 單條語句執行,next命令簡寫。
18 for(i=1; i<=100; i++)
(gdb) n
20 result += i;
(gdb) n
18 for(i=1; i<=100; i++)
(gdb) n
20 result += i;
(gdb) c <--------------------- 繼續運行程序,continue命令簡寫。
Continuing.
result[1-100]=5050 <----------程序輸出。
Breakpoint 2, func (n=250) at tst.c:5
5 int sum=0,i;
(gdb) n
6 for(i=1; i<=n; i++)
(gdb) p i <--------------------- 打印變量i的值,print命令簡寫。
$1 = 134513808
(gdb) n
8 sum+=i;
(gdb) n
6 for(i=1; i<=n; i++)
(gdb) p sum
$2 = 1
(gdb) n
8 sum+=i;
(gdb) p i
$3 = 2
(gdb) n
6 for(i=1; i<=n; i++)
(gdb) p sum
$4 = 3
(gdb) bt <--------------------- 查看函數堆棧。
#0 func (n=250) at tst.c:5
#1 0x080484e4 in main () at tst.c:24
#2 0x400409ed in __libc_start_main () from /lib/libc.so.6
(gdb) finish <--------------------- 退出函數。
Run till exit from #0 func (n=250) at tst.c:5
0x080484e4 in main () at tst.c:24
24 printf("result[1-250] = %d \n", func(250) );
Value returned is $6 = 31375
(gdb) c <--------------------- 繼續運行。
Continuing.
result[1-250]=31375 <----------程序輸出。
Program exited with code 027. <--------程序退出,調試結束。
(gdb) q <--------------------- 退出gdb。
五.gdb調試core文件實例
假設一個程序a.out 生成了一個 core 文件,那么可以通過如下命令來進入調試:
當然如果core文件和a.out沒有在同一個目錄,也可以直接
這種情況下gdb是找不到符號表的,所以需要在進入gdb之后通過
來載入符號表,不管是哪一種方式,進入調試界面之后,按下where或者bt就可以看見出錯的堆棧情況。
轉載請注明出處.http://www.vimer.cn總結
以上是生活随笔為你收集整理的使用gdb调试程序详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于listen的第二个参数backlo
- 下一篇: 数据中心加速,一文说清FPGA与GPU、