《軟件調試的藝術》筆記--檢查和設置變量

1.使用print命令查看變量值

使用print命令(簡寫爲p)可以查看變量值。node

使用例如如下的程序1進行測試。數組

#include <stdio.h>

struct node{
        int index;
        struct node* next;
};

int main(void) {
        struct node head;
        head.index = 1;
        head.next = NULL;

        int i;
        for(i=0; i<3; i++){
                head.index++;
        }

        return 0;
}
(gdb) b main
Breakpoint 1 at 0x804839a: file a.c, line 10.
(gdb) r
Starting program: /root/a.out

Breakpoint 1, main () at a.c:10
10              head.index = 1;
(gdb) n
11              head.next = NULL;
(gdb)
14              for(i=0; i<3; i++){
(gdb)
15                      head.index++;
(gdb)
14              for(i=0; i<3; i++){
(gdb) p head
$1 = {index = 2, next = 0x0}
(gdb) n
15                      head.index++;
(gdb)
14              for(i=0; i<3; i++){
(gdb)
15                      head.index++;
(gdb)
14              for(i=0; i<3; i++){
(gdb) p head
$3 = {index = 4, next = 0x0}


print命令贊成指定可選的格式,好比函數

p/x yui

會以十六進制格式顯示變量,而不是十進制。其它常用的格式爲c(字符),s(字符串),f(浮點型)命令行


2.使用display命令查看變量值

每次遇到斷點,僅僅需要鍵入print命令就行查看變量值,但是,假設知道會在每次遇到斷點時鍵入這個命令,那麼使用
display命令(簡寫爲disp)能節省不少其它的時間。這個命令要求GDB在運行每次有暫停時就輸出指定條目。
使用上面的程序1輸出的調試的結果例如如下:
(gdb) b main
Breakpoint 1 at 0x804839a: file a.c, line 10.
(gdb) b 15
Breakpoint 2 at 0x80483b1: file a.c, line 15.
(gdb) r
Starting program: /root/a.out


Breakpoint 1, main () at a.c:10
10              head.index = 1;
(gdb) disp head
1: head = {index = -1208168460, next = 0x80483d0}
(gdb) c
Continuing.


Breakpoint 2, main () at a.c:15
15                      head.index++;
1: head = {index = 1, next = 0x0}
(gdb)
Continuing.


Breakpoint 2, main () at a.c:15
15                      head.index++;
1: head = {index = 2, next = 0x0}
(gdb)
Continuing.


Breakpoint 2, main () at a.c:15
15                      head.index++;
1: head = {index = 3, next = 0x0}
(gdb)
可以暫時禁用某個顯示項,好比:
dis disp 1
暫時禁用顯示列表中的條目1,條目可以經過 info disp命令檢查。
要又一次啓用條目,使用enable
enable disp 1
要全然刪除條目,使用undisplay(簡寫爲undisp)
undisp 1

3.使用call命令調用函數

使用call函數可以調用被調試程序的函數。
使用如下的程序2進行演示:
#include <stdio.h>

struct node{
        int index;
        char* content;
        struct node* next;
};

void display(struct node head){
        printf("head.index=%d,head.content=%s\n",head.index,head.content);
}

int main(void) {
        struct node head;
        head.index = 1;
        head.content = "yes";
        head.next = NULL;

        int i;
        for(i=0; i<3; i++){
                head.index++;
        }

        display(head);
        return 0;
}

(gdb) b main
Breakpoint 1 at 0x80483f0: file a.c, line 15.
(gdb) r
Starting program: /root/a.out

Breakpoint 1, main () at a.c:15
15              head.index = 1;
(gdb) n
16              head.content = "yes";
(gdb)
17              head.next = NULL;
(gdb)
20              for(i=0; i<3; i++){
(gdb)
21                      head.index++;
(gdb) call display(head)
head.index=1,head.content=yes

4.使用ptype查看變量類型

使用程序2進行調試:
(gdb) b main
Breakpoint 1 at 0x804842a: file a.c, line 16.
(gdb) r
Starting program: /root/a.out

Breakpoint 1, main () at a.c:16
16              head.index = 1;
(gdb) ptype head
type = struct node {
    int index;
    char *content;
    struct node *next;
}
(gdb)

5.監視局部變量

使用info locals命令獲得當前棧幀中所有局部變量的值列表。
使用程序2進行調試:
(gdb) b main
Breakpoint 1 at 0x804842a: file a.c, line 16.
(gdb) r
Starting program: /root/a.out

Breakpoint 1, main () at a.c:16
16              head.index = 1;
(gdb) info locals
head = {index = -1209402059,
  content = 0xb7ff0a50 "U\211\345WV1\366S\350N\212", next = 0x804849b}
i = -1208168460
(gdb) n
17              head.content = "yes";
(gdb)
18              head.next = NULL;
(gdb)
21              for(i=0; i<3; i++){
(gdb) info locals
head = {index = 1, content = 0x8048574 "yes", next = 0x0}
i = -1208168460
(gdb) n
22                      head.index++;
(gdb) info local
head = {index = 1, content = 0x8048574 "yes", next = 0x0}
i = 0
(gdb)

6.檢查動態數組

對如下的程序3進行調試。
#include <stdio.h>
#include <malloc.h>

int main(void){
        int a[3] = {1,2,3};
        int *b = (int*)malloc(3*sizeof(int));
        b[0] = 1;
        b[1] = 2;
        b[2] = 3;
        return 0;
}

(gdb) b main
Breakpoint 1 at 0x80483cd: file b.c, line 5.
(gdb) r
Starting program: /root/a.out

Breakpoint 1, main () at b.c:5
5               int a[3] = {1,2,3};
(gdb) n
6               int *b = (int*)malloc(3*sizeof(int));
(gdb)
7               b[0] = 1;
(gdb)
8               b[1] = 2;
(gdb)
9               b[2] = 3;
(gdb)
10              return 0;
(gdb) p a
$1 = {1, 2, 3}
(gdb) p b
$2 = (int *) 0x804b008
(gdb) p *b
$3 = 1

假設是動態數組,直接使用p命令僅僅能打印一個數。
使用例如如下命令,可以打印出整個數組:
(gdb) p *b@3
$1 = {1, 2, 3}
(gdb) 

語法例如如下:
p *pointer@number_of_elements.

還有一種方式是使用類型強制轉換:
(gdb) p (int [3])*b
$3 = {1, 2, 3}
(gdb)

7.設置變量

在gdb中,值的設置很easy,好比
set x=12
會將x的當前值改動爲12.

可以經過gdb的set args命令設置程序的命令行參數,該命令可以需要下次運行run命令時纔會發生變化。事實上僅僅要在調用
gdb的run命令時使用新參數就能達到相同的效果。

gdb提供info args命令來檢查當前函數的參數。

使用如下的程序4進行調試:
#include <stdio.h>

void display(int i, char* argv)
{
        printf("argv[%d]=%s\n",i,argv);
}

int main(int argc, char* argv[])
{
        int i;
        for (i=0; i<argc; i++) {
                display(i,argv[i]);
        }
        return 0;
}
調試:
(gdb) set args 1 2 3 (gdb) b main Breakpoint 2 at 0x80483f0: file a.c, line 11. (gdb) b display Note: breakpoint 1 also set at pc 0x80483ca. Breakpoint 3 at 0x80483ca: file a.c, line 5. (gdb) r Starting program: /root/a.out 1 2 3 Breakpoint 2, main (argc=4, argv=0xbffff724) at a.c:11 11              for (i=0; i<argc; i++) { (gdb) info args argc = 4 argv = 0xbffff724 (gdb) c Continuing. Breakpoint 1, display (i=0, argv=0xbffff86a "/root/a.out") at a.c:5 5               printf("argv[%d]=%s\n",i,argv); (gdb) c Continuing. argv[0]=/root/a.out Breakpoint 1, display (i=1, argv=0xbffff876 "1") at a.c:5 5               printf("argv[%d]=%s\n",i,argv); (gdb) Continuing. argv[1]=1 Breakpoint 1, display (i=2, argv=0xbffff878 "2") at a.c:5 5               printf("argv[%d]=%s\n",i,argv); (gdb) Continuing. argv[2]=2 Breakpoint 1, display (i=3, argv=0xbffff87a "3") at a.c:5 5               printf("argv[%d]=%s\n",i,argv); (gdb) Continuing. argv[3]=3
相關文章
相關標籤/搜索