zoukankan      html  css  js  c++  java
  • Linux C编程(2) dgb调试

    1. 首先编写一个用于调试的测试程序test.c

    #include <stdio.h>     
    
    int get_sum(int n)
    {
        int sum = 0,i;
        for(i = 1; i <=n ; i++)
        {
            sum+=i;
        }
        return sum;
    }
    int main()
    {
        int i = 100,result;
        result = get_sum(i);
        printf("1+2+...+100=%d
    ",result);
        return 0;
    } 

      编译并运行

    [root@localhost ctest]# gcc test.c -o test
    [root@localhost ctest]# ./test 
    1+2+...+100=5050

      gdb调试程序的命令格式为:gdb 可执行的程序文件名,加上-q选项可以不输出版权说明

    [root@localhost ctest]# gdb -q test
    Reading symbols from /tmp/ctest/test...(no debugging symbols found)...done.
    (gdb) 

      使用q/quit可以退出gdb。

    2. 显示和查找程序源代码

      (1) list:显示10行代码,再次运行时显示接下来的10行代码

      (2) list 5,10:显示5~10行代码

      (3) list test.c:5,10:显示源文件test.c中 的5~10行代码,在调试含有多个源文件程序时使用。  

      (4) list get_sum:显示get_sum函数周围的代码

      (5) list test.c:get_sum:显示源文件test.c中get_sum函数周围的代码,在调试多个源文件程序时使用。

      例:

    (gdb) list 4,10
    4       {
    5           int sum = 0,i;
    6           for(i = 1; i <=n ; i++)
    7           {
    8               sum+=i;
    9           }
    10          return sum;
    (gdb) list get_sum 
    1       #include <stdio.h>     
    2
    3       int get_sum(int n)
    4       {
    5           int sum = 0,i;
    6           for(i = 1; i <=n ; i++)
    7           {
    8               sum+=i;
    9           }
    10          return sum;
    (gdb)

      在调试的过程中如要使用Linux命令,可以在gdb提示符下输入shell命令,如:

    (gdb) shell ls
    datatype.c  file1.c  num_game.c  p3.c           symbalconstant.c  test
     test.c    digui.c     getc.c   p2.c        sequence.c     taijie.c
    (gdb) 

      search 和forward用来从当后行向前查找第一个匹配的字符串,reverse-search用来从当前行向前查找第一个匹配的字符串,如:

    (gdb) search get_sum 
    15          result = get_sum(i);
    (gdb) reverse-search main
    12      int main()
    (gdb) 

    3. 执行程序和获得帮助

      使用gdb -q test只是装入程序,程序并没有运行。运行需输入run命令,如:

    (gdb) run
    Starting program: /tmp/ctest/test 
    1+2+...+100=5050
    
    Program exited normally.
    Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.132.el6.i686
    (gdb) 

      如果想要详细了解某个命令的使用方法,可以使用help命令,如:

    (gdb) help list
    (gdb) help all

    4. 设置和管理断点

      (1) 以行号设置断点,使用break命令,如:

    (gdb) break 8
    Breakpoint 2 at 0x80483da: file test.c, line 8.
    (gdb) 

      第二行为设置断点后的反馈信息,包括:当前设置的断点,断点所在的内存地址及所在行号。输入run后,程序运行到第8行的指令后就暂停。

    (gdb) run
    Starting program: /tmp/ctest/test 
    
    Breakpoint 2, get_sum (n=100) at test.c:8
    8               sum+=i;
    (gdb) 

      (2) 以函数名设置断点,如:

    (gdb) break get_sum 
    Breakpoint 1 at 0x80483ca: file test.c, line 5.
    (gdb) run
    Starting program: /tmp/ctest/test 
    
    Breakpoint 1, get_sum (n=100) at test.c:5
    5           int sum = 0,i;
    Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.132.el6.i686
    (gdb) 

      (3) 以条件表达式设置断点,程序在运行过程中,当某个条件满足时,程序在某行中断暂停执行,其格式为:

      break 行号或函数名 if 条件

    (gdb) break 8 if i==99
    Breakpoint 1 at 0x80483da: file test.c, line 8.
    (gdb) run
    Starting program: /tmp/ctest/test 
    
    Breakpoint 1, get_sum (n=100) at test.c:8
    8               sum+=i;
    Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.132.el6.i686
    (gdb) 

      (4) 不需要指定行号或函数,而是在整个程序运行中当条件表达式的值发生改变时程序就会暂停。,其格式为:

      watch 条件表达式

    [root@localhost ctest]# gdb -q test
    Reading symbols from /tmp/ctest/test...done.
    (gdb) watch i==99 // 由于test没有运行,变量i还没被定义
    No symbol "i" in current context.
    (gdb) break 7  // 设置断点
    Breakpoint 1 at 0x80483da: file test.c, line 7.
    (gdb) run  // 运行至断点处
    Starting program: /tmp/ctest/test 
    
    Breakpoint 1, get_sum (n=100) at test.c:8
    8               sum+=i;
    Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.132.el6.i686
    (gdb) watch i==99  // 变量i已定义,可以设置
    Hardware watchpoint 2: i==99
    (gdb) clear 7  // 删除所设断点
    Deleted breakpoint 1 
    (gdb) continue  //程序继续运行,表达式的值从i==99由原来0变到1,因此程序中断
    Continuing.
    Hardware watchpoint 2: i==99
    
    Old value = 0
    New value = 1
    0x080483e4 in get_sum (n=100) at test.c:6
    6           for(i = 1; i <=n ; i++)
    (gdb) print i  // 显示i
    $1 = 99
    (gdb) print sum  // 显示sum
    $2 = 4851
    (gdb) next
    8               sum+=i;
    (gdb) print i
    $3 = 99
    (gdb) print sum
    $4 = 4851
    (gdb) next  // 继续执行下一条语句
    6           for(i = 1; i <=n ; i++)
    (gdb) print i
    $5 = 99
    (gdb) print sum
    $6 = 4950
    (gdb) next
    8               sum+=i;
    (gdb) print i
    $7 = 100
    (gdb) print sum
    $8 = 4950
    (gdb) next
    6           for(i = 1; i <=n ; i++)
    (gdb) print i
    $9 = 100
    (gdb) print sum
    $10 = 5050
    (gdb) 

    5. 查看当前设置的中断点

      采用info breakpoints命令可以查看当前所有的中断点,如:

    (gdb) break 8
    Breakpoint 1 at 0x80483da: file test.c, line 8.
    (gdb) break 16 if result==5050
    Breakpoint 2 at 0x8048412: file test.c, line 16.
    (gdb) info breakpoints 
    Num     Type           Disp Enb Address    What
    1       breakpoint     keep y   0x080483da in get_sum at test.c:8
    2       breakpoint     keep y   0x08048412 in main at test.c:16
            stop only if result==5050
    (gdb) 

      Num:编号,Type:类型,Disp:指示中断点在生效一次后是否会失去作用,是位dis,否为keep,End:表明当前中断点是否有效,Adress:表示中断所处的内存地址,What:列出中断发生在哪个函数的第几行,最后一行表明这是一个条件中断。

      5. 使中断失效或有效

      使用"disable 断点编号"可以是某个断点失效,程序运行到该断点不会停下来而是继续运行。

      使用“enable 断点编号”可以使某个断点恢复有效。

    (gdb) info breakpoints 
    Num     Type           Disp Enb Address    What
    1       breakpoint     keep y   0x080483da in get_sum at test.c:8
    2       breakpoint     keep y   0x08048412 in main at test.c:16
            stop only if result==5050
    (gdb) disalbe 2
    Undefined command: "disalbe".  Try "help".
    (gdb) 
    (gdb) info breakpoints
    Num     Type           Disp Enb Address    What
    1       breakpoint     keep y   0x080483da in get_sum at test.c:8
    2       breakpoint     keep y   0x08048412 in main at test.c:16
            stop only if result==5050
    (gdb) disable 2
    (gdb) info breakpoints
    Num     Type           Disp Enb Address    What
    1       breakpoint     keep y   0x080483da in get_sum at test.c:8
    2       breakpoint     keep n   0x08048412 in main at test.c:16
            stop only if result==5050
    (gdb) enable 2
    (gdb) info breakpoints 
    Num     Type           Disp Enb Address    What
    1       breakpoint     keep y   0x080483da in get_sum at test.c:8
    2       breakpoint     keep y   0x08048412 in main at test.c:16
            stop only if result==5050
    (gdb) 

    6. 删除断点

      disable只是让某个某个断点暂时失效,断点依然存在于程序中。彻底删除断点可使用clear或delete命令。

      格式为:

      (1) clear:删除程序中所有的断点

      (2) clear 行号:删除此行的断点

      (3) clear 函数名:删除该函数的断点

      (4) delete 断点编号:删除指定编号的断点,如果一次要删除多个断点,各个断点编号以空格隔开。

    [root@localhost ctest]# gdb -q test
    Reading symbols from /tmp/ctest/test...done.
    (gdb) break 6
    Breakpoint 1 at 0x80483d1: file test.c, line 6.
    (gdb) break 7
    Breakpoint 2 at 0x80483da: file test.c, line 7.
    (gdb) break 8 if sum==5050
    Note: breakpoint 2 also set at pc 0x80483da.
    Breakpoint 3 at 0x80483da: file test.c, line 8.
    (gdb) info breakpoints 
    Num     Type           Disp Enb Address    What
    1       breakpoint     keep y   0x080483d1 in get_sum at test.c:6
    2       breakpoint     keep y   0x080483da in get_sum at test.c:7
    3       breakpoint     keep y   0x080483da in get_sum at test.c:8
            stop only if sum==5050
    (gdb) clear 6
    Deleted breakpoint 1 
    (gdb) info breakpoints 
    Num     Type           Disp Enb Address    What
    2       breakpoint     keep y   0x080483da in get_sum at test.c:7
    3       breakpoint     keep y   0x080483da in get_sum at test.c:8
            stop only if sum==5050
    (gdb) delete 2,3
    warning: bad breakpoint number at or near '2,3'
    (gdb) info breakpoints 
    Num     Type           Disp Enb Address    What
    2       breakpoint     keep y   0x080483da in get_sum at test.c:7
    3       breakpoint     keep y   0x080483da in get_sum at test.c:8
            stop only if sum==5050
    (gdb) delete 2 3
    (gdb) info breakpoints 
    No breakpoints or watchpoints.

    7. 查看和设置变量的值

      (1) print命令的格式有:

      print 变量或表达式:打印变量或表达式当前的值

      print 变量=值:对变量进行赋值

      print 表达式@要打印的值的个数:打印以表达式值开始的n个数

      (2) whatis命令,用于显示某个变量或表达式值的数据类型,七个是我:whatis 变量或表达式

    (gdb) run
    The program being debugged has been started already.
    Start it from the beginning? (y or n) y
    Starting program: /tmp/ctest/test 
    
    Breakpoint 1, get_sum (n=100) at test.c:8
    8               sum+=i;
    (gdb) whatis i
    type = int
    (gdb) whatis sum+0.5
    type = double
    (gdb)

      (3) set命令,用于给变量赋值,其格式为:set variable 变量=值,set也可以针对远程调试进行设置,可以用来设置gdb一行的字符数等。

    8. 控制程序的执行

      (1) continue命令:让程序继续执行,直到下一个断点或运行完为止。

      (2) kill命令:用于结束当前程序的调试。

      (3) next和step命令:一次一条执行该代码段,二者的区别是:如果遇到函数调用,next会把该函数当做一条语句来执行,再次输入next会执行函数调用后的语句,而step则会跟踪进入函数,一次一条地执行函数内的代码,直到函数内的代码执行完,才执行函数调用后的语句。

    [root@localhost ctest]# gdb -q test
    Reading symbols from /tmp/ctest/test...done.
    (gdb) list 1,18
    1       #include <stdio.h>     
    2
    3       int get_sum(int n)
    4       {
    5           int sum = 0,i;
    6           for(i = 1; i <=n ; i++)
    7           {
    8               sum+=i;
    9           }
    10          return sum;
    11      }
    12      int main()
    13      {
    14          int i = 100,result;
    15          result = get_sum(i);
    16          printf("1+2+...+100=%d
    ",result);
    17          return 0;
    18      }                              
    (gdb) break 14
    Breakpoint 1 at 0x80483fa: file test.c, line 14.
    (gdb) run
    Starting program: /tmp/ctest/test 
    
    Breakpoint 1, main () at test.c:14
    14          int i = 100,result;
    Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.132.el6.i686
    (gdb) next
    15          result = get_sum(i);
    (gdb) next
    16          printf("1+2+...+100=%d
    ",result);
    (gdb) next
    1+2+...+100=5050
    17          return 0;
    (gdb) 
    (gdb) continue
    Continuing.
    
    Program exited normally.
    (gdb) 
    (gdb) run
    Starting program: /tmp/ctest/test 
    
    Breakpoint 1, main () at test.c:14
    14          int i = 100,result;
    (gdb) step
    15          result = get_sum(i);
    (gdb) step
    get_sum (n=100) at test.c:5
    5           int sum = 0,i;
    (gdb) step
    6           for(i = 1; i <=n ; i++)
    (gdb) 

      (4) nexti和stepi命令

      nexti和stepi命令用来单步执行一条及其指令,注意不是单步执行!一条语句由多条机器指令构成。

      例:for(i=0;i<n;i++),如果是单步执行一条指令,则这行语句要输入多个nexti或stepi才能完成,i=0和i<n会分开执行。

    (gdb) step
    6           for(i = 1; i <=n ; i++)
    (gdb) stepi
    0x080483d8      6           for(i = 1; i <=n ; i++)
    (gdb) stepi
    0x080483e4      6           for(i = 1; i <=n ; i++)
    (gdb) stepi
    0x080483e7      6           for(i = 1; i <=n ; i++)
    (gdb) stepi
    0x080483ea      6           for(i = 1; i <=n ; i++)
    (gdb) stepi
    8               sum+=i;

      

  • 相关阅读:
    前台线程与后台线程的区别
    触发器
    Asp.net AutopostBack 属性
    Spring实战拆书--SpringBean
    侣行APP
    用android去写一个小程序
    java如何使用JUnit进行单元测试
    JDK的安装与配置以及eclipse的使用
    软件工程第一次作业(1)
    软件工程第一次作业(2)
  • 原文地址:https://www.cnblogs.com/mengrennwpu/p/4865432.html
Copyright © 2011-2022 走看看