網絡上已經有很多gdb調試的文章了,為什么我還要寫這篇文章呢,因為本文是寫給gdb新手的,目的就是通過一個簡單的例子來讓新手很快上手。一旦上手入門了,其他的問題就可以自己去搜索搞定了。右邊是gdb的Logo,為啥是條吹泡泡的小魚呢?我也不懂啊。
![[image of Archer
Fish]](/image/aHR0cHM6Ly93d3cuZ251Lm9yZy9zb2Z0d2FyZS9nZGIvaW1hZ2VzL2FyY2hlci5qcGc=.png)
1 #include <stdio.h>
2 3 void print_str(char* str){ 4 printf("%s", str); 5 str[0] = 'a'; 6 printf("\n"); 7 } 8 int main(){ 9 char* str = "hello, world!"; 10 11 print_str(str); 12 13 return 0; 14 }
gcc -g main.c -o main -Wall -O0
-g Produce debugging information in the operating system's native format (stabs, COFF, XCOFF, or DWARF 2). GDB can work with this debugging
information. 簡單來說就是在生成的可執行程序中加上gdb調試用的信息,如代碼的行號和機器碼的對應關系,符號表等信息。沒有這類信息,在gdb里是看不到程序的函數名和變量名的
-o file
Write output to file. 定義輸出文件的名稱
-Wall Turns on all optional warnings which are desirable for normal code. 打開所有的警告信息,可以幫助我們通過warning來發現bug
-O 控制優化的級別, -O0Do not optimize. This is the default. 代碼經過優化后,可能出現機器碼和源代碼對不上的問題。
./main
Segmentation fault
程序出錯啦,段錯誤,一般是訪問越界或者是嘗試修改只讀屬性的內存造成的。
此時,可以用兩種方法來調試這個程序:
GNU gdb (GDB) Red Hat Enterprise Linux (7.0.1-37.el5) Copyright (C) 2009 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-redhat-linux-gnu". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>... Reading symbols from /home/csd/main...done. (gdb)
此時進入了gdb的命令行,跟shell一樣,提供自動補全等功能,所以如果不計得命令的全稱時,可以按tab鍵補全。
此時用 l [list] 命令(l是命令的簡寫,方括號中是命令的全稱)來顯示源碼,也可以 l linenumber 來顯示指定行號處的源碼,也可以用 l 命名空間::類名::函數名來顯示指定的函數,可以按tab鍵補全哦
(gdb) l 1 1 #include <stdio.h> 2 3 void print_str(char* str){ 4 printf("%s", str); 5 str[0] = 'a'; 6 printf("\n"); 7 } 8 int main(){ 9 char* str = "hello, world!"; 10
可以看到默認顯示10行源代碼,想要繼續看10行之后的代碼,可以繼續用 l 命令,也可以直接按回車,會重復上次的命令。
。如果覺得顯示的源代碼行數不夠多,可以用 set listsize number 來設置一次顯示源代碼的行數。設置完成后,可以用 show listsize 命令來查看設置之后 listsize 變量的值。
此時我們想在程序開始處加斷點,使用 b [break] linenumber 命令在指定行處設置斷點,也可以用 b 命名空間::類名::函數名來在指定的函數處設置斷點
(gdb) b 9
Breakpoint 1 at 0x400522: file main.c, line 9.
(gdb) r
Starting program: /home/csd/main
Breakpoint 1, main () at main.c:9
9 char* str = "hello, world!"; (gdb)
此時程序停止在了斷點1處,如果我們想看str的值怎么辦?用 p [print] 變量名 來查看變量的值
(gdb) p str $1 = 0x0 (gdb)
此時還沒有執行給str賦值的操作。然后用 n [next] 來單步執行下一條語句,然后再打印str的值,可以看到str已經被准確初始化了。
(gdb) n 11 print_str(str); (gdb) p str $1 = 0x40063b "hello, world!" (gdb)
此時程序將要執行第11行,print_str函數,我們想單步進入這個函數,可以用 step 命令
(gdb) step print_str (str=0x40063b "hello, world!") at main.c:4 4 printf("%s", str); (gdb)
可以看到程序將要執行main.c文件中的print_str函數處的第4行,同時gdb會顯示函數參數的地址和值。然后我們用 n 來單步執行
(gdb) n 5 str[0] = 'a'; (gdb) n Program received signal SIGSEGV, Segmentation fault. 0x000000000040050b in print_str (str=0x40063b "hello, world!") at main.c:5 5 str[0] = 'a'; (gdb)
單步執行到第5行時出錯了,程序收到操作系統發出的段錯誤信號。此時我們恍然大悟,嘗試修改字符串常量的值,所以出錯了。
./csd/main
Segmentation fault (core dumped)
此時發生段錯誤時,在當前工作目錄下,產生了core dump文件:core.32624
加載core dump文件調試的語法: gdb /path/program-name /path/core-file執行命令:
gdb ./main core.32624
GNU gdb (GDB) Red Hat Enterprise Linux (7.0.1-37.el5)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
./main: No such file or directory.
[New Thread 32624]
Core was generated by `./csd/main'.
Program terminated with signal 11, Segmentation fault.
#0 0x000000000040050b in ?? ()
(gdb)
細心的讀者會發現,gdb的顯示的信息中,提示沒有找到./main這個文件或目錄。這是由於我切換目錄(/home/csd/) 到了上一級目錄(/home),導致gdb找不到main程序的源文件。此時可以設置 dir [directories] 變量來設置源代碼的查找目錄
(gdb) dir ./csd/ Source directories searched: /home/shengdong.csd/./csd:$cdir:$cwd (gdb)
(gdb) bt #0 0x000000000040050b in print_str (str=0x40063b "hello, world!") at main.c:7 #1 0x0000000000400533 in main () at main.c:13 (gdb)
可以看到程序時在main.c函數的第7行出問題的,然后用 l 7 來顯示第7行上下的源代碼,發現問題的所在。
另外,還有一種調試方法:
[1] 用GDB調試程序(一)
陳浩寫的很詳細,總共七部分。四和七在頁面上沒有鏈接,可以google一下,就能找到了。網上也有人整理成了pdf的文檔,方便閱讀。
如果您看了本篇博客,覺得對您有所收獲,請點擊右下角的“推薦”,讓更多人看到!

