GDB調試基礎篇

目錄

一、GDB的來源

二、GDB調試步驟

三、GDB調試基本命令

(1)GDB啓動和退出

(2)運行命令

(3)設置斷點

(4)打印/查看信息

四、總結

參考文獻:


    在各種環境或系統中,爲了能夠幫助程序員更快的定位程序的出錯原因,通常會有相應的調試器,調試器可以看作是程序員的小幫手了,比如:從事Android開發需要會使用Android Studio、從事Java開發需要會使用Eclipse、從事Linux操作系統開發需要會使用GDB等,調試工具是一把窺探程序內部祕密的鑰匙!

   本文主要記錄和總結在Linux環境下GDB調試使用到的基本步驟和命令。

一、GDB的來源

  先來認識一張GDB官方圖標,是不是有點可愛:

                                                                                   

                                                                                    圖1 GDB官方圖標

  在編程過程中,經常聽別人提起GDB、GDB調試、GDB乃程序員的基本素養、GDB從入門到放棄,那麼什麼是GDB呢?

    GDB即GNU調試器(GNU Debugger,簡寫GDB),是GNU軟件系統中的標準調試器,目前主要應用於UNIX和類UNIX操作系統中。它的主要職責便是幫助程序員調試程序啦,俗稱:“解BUG”。

   那GDB有哪些功能呢?

  • 啓動你的程序,可以按照你自定義的要求隨心所欲的運行程序;
  • 可以讓被調試的程序在你所指定的斷點處停住;
  • 當程序被停住時,可以檢查此時你的程序中發生的事;
  • 你可以改變你的程序,將一個BUG修正,從而測試其他的BUG;

二、GDB調試步驟

一般在程序遇到問題時調試過程爲:

  1. gdb <program> 開始調試程序;
  2. set args <args1 args2 ……argsn>設置程序需要的參數;
  3. break <condition> 設置斷點;
  4. run 開始調試程序;
  5. next 執行下一步;
  6. quit 退出調試;

舉個栗子:

有如下的程序,接下來的講解也將使用程序 program.c 作爲例子進行講解(文件名:program.c):

#include <stdio.h>

void printStr(char str[])
{
    printf("%s\n", str);
}

int main(int argc,char *argv[])
{
    if (argc < 2) printf("Error: argc <= 2\n");
    printStr(argv[1]);

    int i = 0;
    int j = 1;
    int k = 2;

    int array[10];
    for (i = 0; i < 10; ++i) {
        array[i] = i;
    }

    printf("array : ");
    for (i = 0; i < 10; ++i) {
        printf("%d ", array[i]);
    }
    printf("\n");
}
[root@192 ~]# gcc -g program.c -o program
[root@192 ~]# gdb program
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-114.el7
Copyright (C) 2013 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 /root/program...done.
(gdb) set args main
(gdb) quit
[root@192 ~]# gcc -g program.c -o program
[root@192 ~]# gdb program
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-114.el7
Copyright (C) 2013 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 /root/program...done.
(gdb) set args this_is_program!
(gdb) break main
Breakpoint 1 at 0x4005d6: file program.c, line 10.
(gdb) run
Starting program: /root/program this_is_program!

Breakpoint 1, main (argc=2, argv=0x7fffffffe528) at program.c:10
10          if (argc < 2) printf("Error: argc <= 2\n");
Missing separate debuginfos, use: debuginfo-install glibc-2.17-307.el7.1.x86_64
(gdb) n
11          printStr(argv[1]);
(gdb) n
this_is_program!
13          int i = 0;
(gdb) quit
A debugging session is active.

        Inferior 1 [process 22607] will be killed.

Quit anyway? (y or n) y
[root@192 ~]#

上面是一個簡單的調試過程,包括設置參數,設置斷點,運行,其中,break,run 都可以採用簡寫b 以及 r來使用。

三、GDB調試基本命令

   GDB命令可以使用全稱或簡寫(一般是首字母)執行;

(1)GDB啓動和退出

  • gdb program : 啓動調試;
  • quit : 簡寫q,退出調試,Ctrl+d也可以退出;  

  在編譯的時候需要加上 -g 調試參數;

[root@192 ~]# gdb program
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-114.el7
Copyright (C) 2013 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 /root/program...done.
(gdb) quit
[root@192 ~]#

(2)運行命令

  • run  : 簡寫 r,運行當前程序,遇到斷點會停止,等待用戶操作;
  • next : 簡寫 n, 單步執行程序,不進入函數內部;
  • step : 簡寫 s,單步執行程序,遇到函數會進入函數內部,注意與next命令區分;
  • continue : 簡寫 c,繼續運行程序,直到遇到斷點或程序結束;

例如:

[root@192 ~]# gdb program
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-114.el7
Copyright (C) 2013 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 /root/program...done.
(gdb) set args this_is_program!
(gdb) b main
Breakpoint 1 at 0x4005d6: file program.c, line 10.
(gdb) b 22
Breakpoint 2 at 0x40062d: file program.c, line 22.
(gdb) r
Starting program: /root/program this_is_program!

Breakpoint 1, main (argc=2, argv=0x7fffffffe528) at program.c:10
10          if (argc < 2) printf("Error: argc <= 2\n");
Missing separate debuginfos, use: debuginfo-install glibc-2.17-307.el7.1.x86_64
(gdb) n
11          printStr(argv[1]);
(gdb) s
printStr (str=0x7fffffffe790 "this_is_program!") at program.c:5
5           printf("%s\n", str);
(gdb) n
this_is_program!
6       }
(gdb) continue
Continuing.

Breakpoint 2, main (argc=2, argv=0x7fffffffe528) at program.c:22
22          printf("array : ");
(gdb) n
23          for (i = 0; i < 10; ++i) {
(gdb) quit
A debugging session is active.

        Inferior 1 [process 22777] will be killed.

Quit anyway? (y or n) y
[root@192 ~]#

其中:

  • set args this_is_program! : 設置輸入參數,可以設置多個;
  • b main : 設置函數斷點;
  • b 22 : 設置行斷點;
  • s : 進入printStr函數;
  • continue : 會在斷點22行處停留,等待用戶操作;

(3)設置斷點

     設置和顯示斷點:

  • break <condition>: 簡寫 b,condition可以是函數名,程序行號,也可以是一個 表達式;
  • info breakpoints : 顯示斷點信息;

例如:

(gdb) set args this_is_program!
(gdb) b main
Breakpoint 1 at 0x4005d6: file program.c, line 10.
(gdb) b printStr
Breakpoint 2 at 0x4005b9: file program.c, line 5.
(gdb) b 22
Breakpoint 3 at 0x40062d: file program.c, line 22.
(gdb) info breakpoints
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000004005d6 in main at program.c:10
2       breakpoint     keep y   0x00000000004005b9 in printStr at program.c:5
3       breakpoint     keep y   0x000000000040062d in main at program.c:22
(gdb)

分別設置了函數和行斷點,其中info breakpoints的顯示信息中:

  • Num : 斷點編號;
  • Type : 類型;
  • Disp : 斷點執行一次之後是否有效,keep有效,dis無效;
  • Enb : 當前斷點是否有效,y有效,n無效;
  • Address : 內存地址;
  • What : 斷點位置;

   刪除斷點:

  • delete Num :  刪除斷點號爲 Num的斷點;
  • disable Num : 暫停斷點號爲Num的斷點;
  • enable Num : 開啓斷點號爲Num的斷點;
  • delete breakpoints : 刪除所有斷點;

例如:

(gdb) info breakpoints
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000004005d6 in main at program.c:10
2       breakpoint     keep y   0x00000000004005b9 in printStr at program.c:5
3       breakpoint     keep y   0x000000000040062d in main at program.c:22
(gdb) disable 1
(gdb) info breakpoints 1
Num     Type           Disp Enb Address            What
1       breakpoint     keep n   0x00000000004005d6 in main at program.c:10
(gdb) enable 1
(gdb) info breakpoints 1
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000004005d6 in main at program.c:10
(gdb) delete 1
(gdb) info breakpoints
Num     Type           Disp Enb Address            What
2       breakpoint     keep y   0x00000000004005b9 in printStr at program.c:5
3       breakpoint     keep y   0x000000000040062d in main at program.c:22
(gdb) delete breakpoints
Delete all breakpoints? (y or n) y
(gdb) info breakpoints
No breakpoints or watchpoints.
(gdb)

(4)打印/查看信息

  • print <condition>: 簡寫 p,打印condition值,condition可以是一個變量/函數調用/表達式等;
  • whatis <valueName>: 查看變量valueName類型;
  • list : 簡寫 l,查看代碼,默認以當前行爲中心查看10行;

例如(代碼中多數使用簡寫):

(gdb) n
11          printStr(argv[1]);
(gdb)
this_is_program!
13          int i = 0;
(gdb)
14          int j = 1;
(gdb)
15          int k = 2;
(gdb) p i
$3 = 0
(gdb) p j
$4 = 1
(gdb) whatis i
type = int
(gdb) l
10          if (argc < 2) printf("Error: argc <= 2\n");
11          printStr(argv[1]);
12
13          int i = 0;
14          int j = 1;
15          int k = 2;
16
17          int array[10];
18          for (i = 0; i < 10; ++i) {
19              array[i] = i;
(gdb)

(5)設置信息

  • set <args args1 args2……> : 設置運行參數;
  • set var <valueName=value> : 設置/修改變量值;

例如(例子中命令多數使用了簡寫):

(gdb) set args this_is_program!
(gdb) b main
Breakpoint 1 at 0x4005d6: file program.c, line 10.
(gdb) r
Starting program: /root/program this_is_program!

Breakpoint 1, main (argc=2, argv=0x7fffffffe528) at program.c:10
10          if (argc < 2) printf("Error: argc <= 2\n");
Missing separate debuginfos, use: debuginfo-install glibc-2.17-307.el7.1.x86_64
(gdb) n
11          printStr(argv[1]);
(gdb) n
this_is_program!
13          int i = 0;
(gdb) n
14          int j = 1;
(gdb) p i
$1 = 0
(gdb) set var i=10
(gdb) p i
$2 = 10
(gdb)

四、總結

    本文只是對GDB的來源、功能、基本命令以及使用方法進行了介紹,當然還有更多更深入的功能,接下來的文章會進一步介紹。

參考文獻:

[1] http://www.gnu.org/software/gdb/ (gdb 官方網站)

[2] https://download.csdn.net/download/u011074149/12553017 (gdb 使用手冊)

[3] https://linuxtools-rst.readthedocs.io/zh_CN/latest/tool/gdb.html

[4] https://blog.csdn.net/niyaozuozuihao/article/details/91802994

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