GDB調試
啓動程序準備調試
GDB yourpram
或者
先輸入GDB
而後輸入 file yourpramlinux
而後使用run或者r命令開始程序的執行,也能夠使用 run parameter將參數傳遞給該程序express
參數列表centos
命令ide |
命令縮寫函數 |
命令說明ui |
listspa |
ldebug |
顯示多行源代碼unix |
break調試 |
b |
設置斷點,程序運行到斷點的位置會停下來 |
info |
i |
描述程序的狀態 |
run |
r |
開始運行程序 |
display |
disp |
跟蹤查看某個變量,每次停下來都顯示它的值 |
step |
s |
執行下一條語句,若是該語句爲函數調用,則進入函數執行其中的第一條語句 |
next |
n |
執行下一條語句,若是該語句爲函數調用,不會進入函數內部執行(即不會一步步地調試函數內部語句) |
|
p |
打印內部變量值 |
continue |
c |
繼續程序的運行,直到遇到下一個斷點 |
set var name=v |
|
設置變量的值 |
start |
st |
開始執行程序,在main函數的第一條語句前面停下來 |
file |
|
裝入須要調試的程序 |
kill |
k |
終止正在調試的程序 |
watch |
|
監視變量值的變化 |
backtrace |
bt |
查看函數調用信息(堆棧) |
frame |
f |
查看棧幀 f n 切換到編號爲n的棧 |
quit |
q |
退出GDB環境 |
//e.c #include <stdio.h> void debug(char *str) { printf("debug info :%s\n",str ); } main(int argc,char *argv[]){ int i,j; j=0; for(i=0;i<10;i++){ j+=5; printf("now a=%d\n", j); } }
gcc -g -o e e.c
調試gdb e
或者輸入gdb
而後 file e
list 命令用法
list命令顯示多行源代碼,從上次的位置開始顯示,默認狀況下,一次顯示10行,第一次使用時,從代碼起始位置顯示
gdb) list 1 #include <stdio.h> 2 void debug(char *str) 3 { 4 printf("debug info :%s\n",str ); 5 } 6 main(int argc,char *argv[]){ 7 int i,j; 8 j=0; 9 for(i=0;i<10;i++){ 10 j+=5; (gdb)
list n顯示已第n行未中心的10行代碼
(gdb) list 8 3 { 4 printf("debug info :%s\n",str ); 5 } 6 main(int argc,char *argv[]){ 7 int i,j; 8 j=0; 9 for(i=0;i<10;i++){ 10 j+=5; 11 printf("now a=%d\n", j); 12 } (gdb)
list functionname顯示以functionname的函數爲中心的10行代碼
(gdb) list main 1 #include <stdio.h> 2 void debug(char *str) 3 { 4 printf("debug info :%s\n",str ); 5 } 6 main(int argc,char *argv[]){ 7 int i,j; 8 j=0; 9 for(i=0;i<10;i++){ 10 j+=5; (gdb)
list - 顯示剛纔打印過的源代碼以前的代碼
(gdb) list 10 5 } 6 main(int argc,char *argv[]){ 7 int i,j; 8 j=0; 9 for(i=0;i<10;i++){ 10 j+=5; 11 printf("now a=%d\n", j); 12 } 13 }(gdb) list - 1 #include <stdio.h> 2 void debug(char *str) 3 { 4 printf("debug info :%s\n",str ); (gdb)
斷點命令break
break location:在location位置設置斷點,該位置能夠爲某一行,某函數名或者其它結構的地址
GDB會在執行該位置的代碼以前停下來
gdb) list 1 #include <stdio.h> 2 void debug(char *str) 3 { 4 printf("debug info :%s\n",str ); 5 } 6 main(int argc,char *argv[]){ 7 int i,j; 8 j=0; 9 for(i=0;i<10;i++){ 10 j+=5; (gdb) 11 printf("now a=%d\n", j); 12 } 13 }(gdb) break 10 Breakpoint 1 at 0x40050a: file e.c, line 10. (gdb) r Starting program: /mnt/hgfs/www/c/gcc/e Breakpoint 1, main (argc=1, argv=0x7fffffffe548) at e.c:10 10 j+=5; (gdb) c Continuing. now a=5 Breakpoint 1, main (argc=1, argv=0x7fffffffe548) at e.c:10 10 j+=5; (gdb) c Continuing. now a=10 Breakpoint 1, main (argc=1, argv=0x7fffffffe548) at e.c:10 10 j+=5; (gdb)
使用delete breakpoints 斷點號 刪除斷點
這裏的斷點號表示的是第幾個斷點,剛纔執行break 10返回 reakpoint 1 at 0x40050a: file e.c, line 10.
中的1表示該斷點的標號,所以使用 delete breakpoints 1表示刪除第10行所定義的斷點
clear n表示清除第n行的斷點,所以clear 10等同於delete breakpoints 1
disable/enable n表示使得編號爲n的斷點暫時失效或有效
可以使用info查看斷點相關的信息
info breakpoints
gdb) info breakpoints No breakpoints or watchpoints. (gdb) break 10 Breakpoint 2 at 0x40050a: file e.c, line 10. (gdb) break 9 Breakpoint 3 at 0x400501: file e.c, line 9. (gdb) info breakpoints Num Type Disp Enb Address What 2 breakpoint keep y 0x000000000040050a in main at e.c:10 3 breakpoint keep y 0x0000000000400501 in main at e.c:9
display命令
查看參數的值
(gdb) break 10 Breakpoint 1 at 0x40050a: file e.c, line 10. (gdb) r Starting program: /mnt/hgfs/www/c/gcc/e Breakpoint 1, main (argc=1, argv=0x7fffffffe548) at e.c:10 10 j+=5; (gdb) display j 1: j = 0 (gdb) c Continuing. now a=5 Breakpoint 1, main (argc=1, argv=0x7fffffffe548) at e.c:10 10 j+=5; 1: j = 5 (gdb) display 1: j = 5 (gdb) display i 2: i = 1 (gdb) display j 3: j = 5 (gdb) display j*2 4: j*2 = 10 (gdb) info display Auto-display expressions now in effect: Num Enb Expression 4: y j*2 3: y j 2: y i 1: y j
也能夠使用disable,enable,delete,info命令修改及查看其狀態,用法與對斷點的同樣
step及next命令
step可以使得程序逐條執行,即執行完一條語句而後在嚇一跳語句前停下來,等待用戶的命令
通常使用step命令是,可以使用display或者watch命令查看變量的變化,從而判斷程序行爲是否符合要求
當下一條指令爲函數時,s進入函數內部,在其第一條語句前停下來
step n,next n 表示連續但不執行n條指令,若是期間遇到斷點,則停下來
(gdb) list 1 #include <stdio.h> 2 void debug(char *str) 3 { 4 printf("debug info :%s\n",str ); 5 } 6 7 main(int argc,char *argv[]){ 8 int i,j; 9 j=0; 10 for(i=0;i<10;i++){ (gdb) 11 j+=5; 12 printf("now j=%d\n", j); 13 debug("x=======x"); 14 } 15 }(gdb) Line number 16 out of range; e.c has 15 lines. (gdb) break 11 Breakpoint 1 at 0x40050a: file e.c, line 11. (gdb) r Starting program: /mnt/hgfs/www/c/gcc/e1 Breakpoint 1, main (argc=1, argv=0x7fffffffe538) at e.c:11 11 j+=5; (gdb) s 12 printf("now j=%d\n", j); (gdb) s __printf (format=0x400648 "now j=%d\n") at printf.c:30 30 { (gdb) bt #0 __printf (format=0x400648 "now j=%d\n") at printf.c:30 #1 0x0000000000400525 in main (argc=1, argv=0x7fffffffe538) at e.c:12 (gdb) n 34 va_start (arg, format); (gdb) n 35 done = vfprintf (stdout, format, arg); (gdb) n now j=5 39 } (gdb) bt #0 __printf (format=<value optimized out>) at printf.c:39 #1 0x0000000000400525 in main (argc=1, argv=0x7fffffffe538) at e.c:12 (gdb) n main (argc=1, argv=0x7fffffffe538) at e.c:13 13 debug("x=======x"); (gdb) n debug info :x=======x 10 for(i=0;i<10;i++){ (gdb) s Breakpoint 1, main (argc=1, argv=0x7fffffffe538) at e.c:11 11 j+=5; (gdb) s 12 printf("now j=%d\n", j); (gdb) n now j=10 13 debug("x=======x"); (gdb) n debug info :x=======x 10 for(i=0;i<10;i++){ (gdb)
watch
watch可設置觀察點(watchpoint)。使用觀察點能夠使得當某表達式的值發生變化時,程序暫停執行。
執行該命令前,必須保證程序已經運行
(gdb) list 1 #include <stdio.h> 2 void debug(char *str) 3 { 4 printf("debug info :%s\n",str ); 5 } 6 7 main(int argc,char *argv[]){ 8 int i,j; 9 j=0; 10 for(i=0;i<10;i++){ (gdb) 11 j+=5; 12 printf("now j=%d\n", j); 13 debug("x=======x"); 14 } 15 }(gdb) Line number 16 out of range; e.c has 15 lines. (gdb) b main Breakpoint 1 at 0x4004fa: file e.c, line 9. (gdb) r Starting program: /mnt/hgfs/www/c/gcc/e1 Breakpoint 1, main (argc=1, argv=0x7fffffffe538) at e.c:9 9 j=0; (gdb) watch j Hardware watchpoint 2: j (gdb) c Continuing. Hardware watchpoint 2: j Old value = 0 New value = 5 main (argc=1, argv=0x7fffffffe538) at e.c:12 12 printf("now j=%d\n", j); (gdb) c Continuing. now j=5 debug info :x=======x Hardware watchpoint 2: j Old value = 5 New value = 10 main (argc=1, argv=0x7fffffffe538) at e.c:12 12 printf("now j=%d\n", j);
print命令
(gdb) list 1 #include <stdio.h> 2 void debug(char *str) 3 { 4 printf("debug info :%s\n",str ); 5 } 6 7 main(int argc,char *argv[]){ 8 int i,j; 9 j=0; 10 for(i=0;i<10;i++){ (gdb) 11 j+=5; 12 printf("now j=%d\n", j); 13 debug("x=======x"); 14 } 15 }(gdb) Line number 16 out of range; e.c has 15 lines. (gdb) break 12 Breakpoint 1 at 0x40050e: file e.c, line 12. (gdb) r Starting program: /mnt/hgfs/www/c/gcc/e1 Breakpoint 1, main (argc=1, argv=0x7fffffffe538) at e.c:12 12 printf("now j=%d\n", j); (gdb) p j $1 = 5 (gdb) c Continuing. now j=5 debug info :x=======x Breakpoint 1, main (argc=1, argv=0x7fffffffe538) at e.c:12 12 printf("now j=%d\n", j); (gdb) p i,j $2 = 10 (gdb) p j $3 = 10 (gdb)
set var name=value
set args 可指定運行時參數(當main函數須要參數時 如:set args 10 20 30 40 50)
show args 命令能夠查看設置好的運行參數
在程序運行中動態改變變量的值
(gdb) list 1 #include <stdio.h> 2 void debug(char *str) 3 { 4 printf("debug info :%s\n",str ); 5 } 6 7 main(int argc,char *argv[]){ 8 int i,j; 9 j=0; 10 for(i=0;i<10;i++){ (gdb) 11 j+=5; 12 printf("now j=%d\n", j); 13 debug("x=======x"); 14 } 15 }(gdb) Line number 16 out of range; e.c has 15 lines. (gdb) break main Breakpoint 1 at 0x4004fa: file e.c, line 9. (gdb) r Starting program: /mnt/hgfs/www/c/gcc/e1 Breakpoint 1, main (argc=1, argv=0x7fffffffe538) at e.c:9 9 j=0; (gdb) watch i Hardware watchpoint 2: i (gdb) watch j Hardware watchpoint 3: j (gdb) c Continuing. Hardware watchpoint 3: j Old value = 0 New value = 5 main (argc=1, argv=0x7fffffffe538) at e.c:12 12 printf("now j=%d\n", j); (gdb) c Continuing. now j=5 debug info :x=======x Hardware watchpoint 2: i Old value = 0 New value = 1 0x0000000000400533 in main (argc=1, argv=0x7fffffffe538) at e.c:10 10 for(i=0;i<10;i++){ (gdb) c Continuing. Hardware watchpoint 3: j Old value = 5 New value = 10 main (argc=1, argv=0x7fffffffe538) at e.c:12 12 printf("now j=%d\n", j); (gdb) c Continuing. now j=10 debug info :x=======x Hardware watchpoint 2: i Old value = 1 New value = 2 0x0000000000400533 in main (argc=1, argv=0x7fffffffe538) at e.c:10 10 for(i=0;i<10;i++){ (gdb) c Continuing. Hardware watchpoint 3: j Old value = 10 New value = 15 main (argc=1, argv=0x7fffffffe538) at e.c:12 12 printf("now j=%d\n", j); (gdb) c Continuing. now j=15 debug info :x=======x Hardware watchpoint 2: i Old value = 2 New value = 3 0x0000000000400533 in main (argc=1, argv=0x7fffffffe538) at e.c:10 10 for(i=0;i<10;i++){ (gdb) c Continuing. Hardware watchpoint 3: j Old value = 15 New value = 20 main (argc=1, argv=0x7fffffffe538) at e.c:12 12 printf("now j=%d\n", j); (gdb) c Continuing. now j=20 debug info :x=======x Hardware watchpoint 2: i Old value = 3 New value = 4 0x0000000000400533 in main (argc=1, argv=0x7fffffffe538) at e.c:10 10 for(i=0;i<10;i++){ (gdb) set var i=8 (gdb) c Continuing. Hardware watchpoint 3: j Old value = 20 New value = 25 main (argc=1, argv=0x7fffffffe538) at e.c:12 12 printf("now j=%d\n", j); (gdb) c Continuing. now j=25 debug info :x=======x Hardware watchpoint 2: i Old value = 8 New value = 9 0x0000000000400533 in main (argc=1, argv=0x7fffffffe538) at e.c:10 10 for(i=0;i<10;i++){ (gdb) c Continuing. Hardware watchpoint 3: j Old value = 25 New value = 30 main (argc=1, argv=0x7fffffffe538) at e.c:12 12 printf("now j=%d\n", j); (gdb) c Continuing. now j=30 debug info :x=======x Hardware watchpoint 2: i Old value = 9 New value = 10 0x0000000000400533 in main (argc=1, argv=0x7fffffffe538) at e.c:10 10 for(i=0;i<10;i++){ (gdb) c Continuing. Watchpoint 2 deleted because the program has left the block in which its expression is valid. Watchpoint 3 deleted because the program has left the block in which its expression is valid. __libc_start_main (main=0x4004eb <main>, argc=1, ubp_av=0x7fffffffe538, init=<value optimized out>, fini=<value optimized out>, rtld_fini=<value optimized out>, stack_end=0x7fffffffe528) at libc-start.c:258 258 exit (result); (gdb) c Continuing. Program exited with code 026.
函數調用相關的
backtrace
可以使用frame 查看堆棧中某一幀的信息
(gdb) list 1 #include <stdio.h> 2 void debug(char *str) 3 { 4 printf("debug info :%s\n",str ); 5 } 6 7 main(int argc,char *argv[]){ 8 int i,j; 9 j=0; 10 for(i=0;i<10;i++){ (gdb) 11 j+=5; 12 printf("now j=%d\n", j); 13 debug("x=======x"); 14 } 15 }(gdb) Line number 16 out of range; e.c has 15 lines. (gdb) b 13 Breakpoint 1 at 0x400525: file e.c, line 13. (gdb) r Starting program: /mnt/hgfs/www/c/gcc/e1 now j=5 Breakpoint 1, main (argc=1, argv=0x7fffffffe538) at e.c:13 13 debug("x=======x"); (gdb) s debug (str=0x400652 "x=======x") at e.c:4 4 printf("debug info :%s\n",str ); (gdb) bt #0 debug (str=0x400652 "x=======x") at e.c:4 #1 0x000000000040052f in main (argc=1, argv=0x7fffffffe538) at e.c:13 (gdb) s __printf (format=0x400638 "debug info :%s\n") at printf.c:30 30 { (gdb) bt #0 __printf (format=0x400638 "debug info :%s\n") at printf.c:30 #1 0x00000000004004e9 in debug (str=0x400652 "x=======x") at e.c:4 #2 0x000000000040052f in main (argc=1, argv=0x7fffffffe538) at e.c:13 (gdb) s 34 va_start (arg, format); (gdb) bt #0 __printf (format=0x400638 "debug info :%s\n") at printf.c:34 #1 0x00000000004004e9 in debug (str=0x400652 "x=======x") at e.c:4 #2 0x000000000040052f in main (argc=1, argv=0x7fffffffe538) at e.c:13 (gdb) s 35 done = vfprintf (stdout, format, arg); (gdb) s _IO_vfprintf_internal (s=0x333a58f040, format=0x400638 "debug info :%s\n", ap=0x7fffffffe330) at vfprintf.c:236 236 int save_errno = errno; (gdb) bt #0 _IO_vfprintf_internal (s=0x333a58f040, format=0x400638 "debug info :%s\n", ap=0x7fffffffe330) at vfprintf.c:236 #1 0x000000333a24effa in __printf (format=<value optimized out>) at printf.c:35 #2 0x00000000004004e9 in debug (str=0x400652 "x=======x") at e.c:4 #3 0x000000000040052f in main (argc=1, argv=0x7fffffffe538) at e.c:13 (gdb) c Continuing. debug info :x=======x now j=10 Breakpoint 1, main (argc=1, argv=0x7fffffffe538) at e.c:13 13 debug("x=======x"); (gdb) bt #0 main (argc=1, argv=0x7fffffffe538) at e.c:13
GDB段錯誤調試
所謂段錯誤就是對內存的非法訪問
採用GDB調試段錯誤有2種方法
1.在GDB中運行目標程序,當發生段錯誤時,GDB中運行的程序會自動停下來
2.直接運行目標程序,使其在發生段錯誤時產生內存轉儲(core dump)文件,GDB對該文件進行調試
abort.c
#include <stdio.h> #include <stdlib.h> void recurse(void) { static int i; if( ++i == 3) abort(); else recurse(); } int main(int argc,char ** argv){ recurse(); }
gcc -g -o abort abort.c 使用gdb調試 Line number 15 out of range; abort.c has 14 lines. (gdb) r Starting program: /mnt/hgfs/www/c/gcc/abort Program received signal SIGABRT, Aborted. 0x000000333a232495 in raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64 64 return INLINE_SYSCALL (tgkill, 3, pid, selftid, sig); (gdb) bt #0 0x000000333a232495 in raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64 #1 0x000000333a233c75 in abort () at abort.c:92 #2 0x00000000004004e7 in recurse () at abort.c:8 #3 0x00000000004004ec in recurse () at abort.c:10 #4 0x00000000004004ec in recurse () at abort.c:10 #5 0x0000000000400502 in main (argc=1, argv=0x7fffffffe528) at abort.c:13 顯示在recurse函數調用了3次後調用了abort函數,產生段錯誤
使用內存轉儲文件
ulimit -a
[root@centos1 gcc]# ulimit -a core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 7331 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 10240 cpu time (seconds, -t) unlimited max user processes (-u) 7331 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited core file size 此時是0
ulimit -c unlimited 設置爲不受限制
執行 ./abort 產生內存轉儲文件
ls 可看到一個名爲core且以進程號爲後綴的文件
core.6289
gdb abort core.6289bt方法同上一個gdb調試