zoukankan      html  css  js  c++  java
  • 《软件调试的艺术》笔记--检查和设置变量

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

    使用print命令(简写为p)能够查看变量值。

    使用例如以下的程序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 y

    会以十六进制格式显示变量,而不是十进制。其它经常使用的格式为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
    ",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 "U211345WV1366S350N212", 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
    ",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 ",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 ",i,argv);
    (gdb)
    Continuing.
    argv[1]=1

    Breakpoint 1, display (i=2, argv=0xbffff878 "2") at a.c:5
    5               printf("argv[%d]=%s ",i,argv);
    (gdb)
    Continuing.
    argv[2]=2

    Breakpoint 1, display (i=3, argv=0xbffff87a "3") at a.c:5
    5               printf("argv[%d]=%s ",i,argv);
    (gdb)
    Continuing.
    argv[3]=3
  • 相关阅读:
    学习练习 java输入输出流 练习题1
    学习总结 java Iterator迭代器练习
    学习总结 java 输入输出流
    学习记录 java 哈希
    学习记录 java 链表知识
    学习总结 java 异常
    学习练习 java 集合
    web压缩gzip响应
    web乱码问题
    web附件中文名
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/3896851.html
Copyright © 2011-2022 走看看