GDB隨筆(一)

gcc -g main.c -o main
  • 在編譯的時候必須加上-g,生成的目標文件才能夠進行調試。(我們調試的是目標文件)
  • -g選項的作用是在目標文件中加入源代碼的信息,保證gdb能找到源文件。
  • -o選項,相當於指定一個文件作爲目標文件。

可以做一個實驗:由main.c生成main(-g),然後將m**在目標文件中加入源代碼的信息,保證gdb能找到源文件。ain.c改成其他名字,然後調用gdb main,就會發現對gdb使用命令(list),提示:沒有那個目錄或文件;但是再將源文件改回原來的名稱,那麼命令也可以正常調用;說明,-g選項不是把源文件放入目標代碼中,而是建立一種聯繫,


命令種類:GDB中將命令劃分爲幾個類別,可以通過help進行查看。此外,還可以通過help還可以查詢具體某個指令的功能。

(gdb) help
List of classes of commands:

aliases -- Aliases of other commands
breakpoints -- Making program stop at certain points
data -- Examining data
files -- Specifying and examining files
internals -- Maintenance commands
obscure -- Obscure features
running -- Running the program
stack -- Examining the stack
status -- Status inquiries
support -- Support facilities
tracepoints -- Tracing of program execution without stopping the program
user-defined -- User-defined commands

Type "help" followed by a class name for a list of commands in that class.
Type "help all" for the list of all commands.
Type "help" followed by command name for full documentation.
Type "apropos word" to search for commands related to "word".
Command name abbreviations are allowed if unambiguous.

list命令,這是一個非常簡單而且基礎的命令。
其功能:列出從某一行開始接下來十行的內容或者某個函數的內容。

list 1  表示列舉第一行至第十行的內容
list 表示從上次list結束的位置開始顯示十行內容,初始爲1
list  function_name   顯示某個函數的內容
簡寫:l

  • 採用start命令進行斷點調試;temporary breakpoint表示下一條將要執行的指令。
(gdb) start
Temporary breakpoint 1 at 0x6de: file HelloWorld.c, line 12.
Starting program: /home/bluephantom/文檔/C編程一站式/gdbHelloWorld 

Temporary breakpoint 1, main () at HelloWorld.c:12
12  {
  • 可通過next(n)命令進行執行下一條指令
  • 可通過step(s)命令進入函數中去執行
  • 可通過backtrace(bt)命令查詢函數狀態
(gdb) bt
#0  add_range (low=1, high=10) at main.c:6
#1  0x080483c1 in main () at main.c:14
可見當前的add_range函數是被main函數調用的,main傳進來的參數是
low=1,high=10。main函數的棧幀編號爲1,add_range的棧幀編號爲0。
後調用的在上層!
  • 用info命令(簡寫爲i)查看各種信息

    • i locals:查看局部變量信息
    • i breakpoints:查看斷點信息
    • i watchpoints:查看觀察點信息
  • 用frame命令(簡寫f)進入某一個棧幀(用數字表示),在棧幀中可以查看對應函數的局部變量及其對應信息。(使用frame並沒有使程序跳轉到此棧幀,而是只是爲了查看某些信息)

  • 用print命令(簡寫p)+ 局部變量,打印某一個局部變量的值。

  • 用finsih命令,可以結束當前函數,回到被調用位置;

  • 用set var命令,後面加變量可以直接進行賦值,對於數組,也可以使用下標進行單獨賦值;
    (gdb) set var result[0]=50
    這裏寫圖片描述


  • 採用display+變量,可以跟蹤顯示變量的值,每一次next都會將其值顯示出來。採用undisplay可以取消跟蹤(通過加對應的標號,單個取消;否則全部取消)
(gdb) display i
2: i = 0
  • 斷點(breakpoint)調試:使用break命令(簡寫b)+行數(函數名),在該行/函數開頭設置斷點,然後搭配continue(簡寫c) ; 可以通過info(info breakpoints)查看設置了多少斷點;
  • 刪除斷點:delete breakpoints 斷點標號,

  • 斷點加單步”是使用調試器的基本方法。至於應該在哪裏設置斷點,怎麼知道哪些代碼可以跳過而哪些代碼要慢慢走,也要通過對錯誤現象的分析和假設來確定,就像以前分析確定在哪裏插入printf語句一樣。

  • 禁用斷點(暫時使其無作用),disable breakpoints 序號; 啓用斷點:enable breakpoints 序號;

  • break 9 if sum != 0 :設置斷點在滿足某個條件時才激活

  • run命令(簡寫爲r)重新從程序開頭連續執行
    這裏寫圖片描述


#include <stdio.h>

int main(void)
{
    int sum = 0, i = 0;
    char input[5];

    while (1) {
        sum = 0;
        scanf("%s", input);
        for (i = 0; input[i] != '\0'; i++)
            sum = sum*10 + input[i] - '0';
        printf("input=%d\n", sum);
    }
    return 0;
}


$ gdb main
......
(gdb) start
Breakpoint 1 at 0x80483b5: file main.c, line 5.
Starting program: /home/akaedu/main 
main () at main.c:5
5       int sum = 0, i = 0;
(gdb) n
9           sum = 0;
(gdb) (直接回車)
10          scanf("%s", input);
(gdb) (直接回車)
12345
11          for (i = 0; input[i] != '\0'; i++)
(gdb) p input
$1 = "12345"


(gdb) x/7b input
0xbfb8f0a7: 0x31    0x32    0x33    0x34    0x35    0x00    0x00

x命令:打印存儲器中的內容。7b是打印格式,b表示每個字節一組,7表示打印7組。開頭表示的是起始地址。
觀察點(watchpoint)與斷點:斷點是當程序執行到某一代碼行時中斷,而觀察點是當程序訪問某一存儲單元時中斷。(觀察點跟蹤單元)
watch + 變量 :觀察某個變量
觀察點也是通過continue進行執行下次操作;


  • 段錯誤(segment fault):在gdb中運行,遇到段錯誤會自動停下來。這個時候可以調用backtrace(bt)查看是在哪個函數內發生錯誤,然後進行修改。

  • 如果某個函數中發生訪問越界,很可能並不立即產生段錯誤,而在函數返回時卻產生段錯誤。


until(簡寫u):執行到某一行爲止;(可以加函數名,也可以加行號)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章