Linux环境下C编程指南(第二版) -- gdb调试工具

四、gdb调试工具
       gdb主要提供的功能:
       监视程序中变量的值的变化
       设置断点,使程序在指定的代码行上暂停执行,便于观察
       单步执行代码
       分析崩溃程序产生的core文件
 
       使用命令:
       gdb filename   装入可执行文件进行调试
      
       注:由于调试需要加入调试信息,在编译是需要加入-g选项或-ggdb3选项
      
       调试:
       # gcc filename  进入调试环境
      
       (gdb) break main          在main的下一行代码处加入断点
       (gdb) break n                      在第n行加入断点
      
       (gdb) run               运行程序
       (gdb) step / s         单步执行,
 
       (gdb) print 表达式    打印变量的值如 print input  打印变量input的值
       (gdb) print 变量=表达式  设置变量的值
       (gdb) print 开始表达式@要打印的连续内存空间大小   打印一段内存的内容
      
       (gdb) display 变量值  执行到断点是会显示变量值,可以观察表达式的值的变化(需要在表达式(变量)作用范围内,一旦出了变量的作用范围不再显示变量值)
      
       (gdb) next   与step相区别,next不能跟踪到函数内部,也即跳入与跳过的区别。
      
       (gdb) quit   退出调试环境
      
       使用代码:
       #include <stdio.h>
 
       int getinput( void);
       void printmessage(int counter, int input);
 
       int main(void)
       {
          int counter = 0;
          int input = 0;
 
         for(counter = 0; counter <= 200; counter++)
         {
             input = getinput();
             if(input == -1)
                end(0);
 
             printmessage(counter, input);
         }
 
         return 0;
       }
 
       int getinput(void )
       {
          int input;
          printf("Enter an integer, or use -1 to exit:");
                 scanf("%d", &input);
          return input;
       }
 
       void printmessage(int counter, int input)
       {
         static int lastnum = 0;
         counter ++;
          printf("For number %d, you enterd %d(%d more than last time)\n", counter, input, input-lastnum);
          lastnum = input;
       }
      
       显示数据命令:
       显示命令最常用的是display 和print命令,另外还有printf 和 set命令
      
       程序如下:
       #include <stdio.h>
       #include <stdlib.h>
       #include <string.h>
 
       typedef struct TAG_datastruct{
           char * string;
           int checksum;
       }datastruct;
 
       datastruct * getinput( void);
       void printmessage(datastruct * todisp);
 
       int main(void)
       {
           int counter = 0;
           int maxval = 0;
           datastruct * svalues[200];
 
           for(counter = 0; counter < 200; counter++)
           {
               svalues[counter] = getinput();
              if(!svalues[counter])
                  break;
              maxval = counter;
           }
           printmessage(svalues[maxval/2]);
       
           return 0;
       }
 
       datastruct * getinput( void)
       {
           char input[80];
           datastruct * instruct;
           int counter;
 
           printf("Enter a string, or leave blank when done:");
           fgets(input, 79, stdin);
           input[strlen(input)-1] = 0;
           if(strlen(input) == 0)
               return NULL;
           instruct = malloc(sizeof(datastruct));
          instruct->string = strdup(input);
           instruct->checksum = 0;
 
      for(counter = 0; counter < strlen(instruct->string); counter++)
      {
               instruct->checksum += instruct->string[counter];
       }
           return instruct;
       }
 
       void printmessage(datastruct * todisp)
       {
           printf("This structure has a checksum of %d.Its string is:\n", todisp->checksum);
           puts(todisp->string);   
       }
      
       $ gdb test2     进入调试环境
       (gdb) run         运行程序
       (gdb) print svalues     打印一个数组(svalues是一个结构体数组)
      
       (gdb) print svalues[0]->checksum   打印结构体的一个成员
       (gdb) print input            打印一个字符串数组,
       (gdb) print input@20   打印input地址处20个内存单元的内容
      
       (gdb) print input[0]     打印input数组的第一个元素
      
       (gdb) finish 强制结束调试
      
       内存检查命令:
       x/format address     format为显示内存单元个数和显示方式组成:如x/2c 以字符形式显示两个内存单元
       (gdb) x/2c 0x9813008
       (gdb) x/2c instruct
       (gdb) x/2c instruct->string
 
       x/2x  以十六进制形式显示   x/2o  以八进制形式显示   x/2d 以十进制形式显示
 
       printf命令:
       printf  “%2.2s\n”, (char*)0x981e018
       printf  “%2.2s\n”, instruct->string
      
       %2.2s\n  第一个2表示最多输出2个单元第二个2表示从0x981e018开始的两个
 
       set命令在程序调试过程中设置变量的值。
 
使用断点:
       (gdb) break test2.c:21  在test2.c文件的第21行设置断点
       (gdb) break 23             在调试文件的第23行设置断点
       (gdb) break printmessage  在调试文件的breakmessage函数处设置断点
      
       查看当前调试程序的断点:
       info break(b)
       编号  类型               可用       地址     断点信息
       Num  Type                  Disp  Enb       Address  What
       1     breakpoint     keep   y        0x080484b9  in main at test2.c:15
       2     breakpoint     keep   n        0x08948630  in printmessage at test2.c:57
 
       run 到断点处,执行continue命令恢复程序运行。
       continue   cont  两个命令作用相同
       cont 2 跳过两次断点
 
       (gdb) bbreak 32   在32行加入一个临时断点,只能断点一次
 
       (gdb) enable 3    将断点3设置为可用
       (gdb) disable 3    将断点3设置为不可用
       (gdb) delete 2     将断点2删除
       (gdb) clear 行号  clear 23 将23行的断点清除掉。注意此处是行号,而delete使用的是断点编号。
 
使用观察窗口:
       (gdb) watch counter>15
       当表达式满足条件时,显示变量的值
 
查看栈信息:
       backtrace 或 bt 查看栈信息
       (gdb) bt         查看当前调用栈的所有信息
       (gdb) backtrace <n>   打印栈顶n层的栈信息
       (gdb) bt <-n>                      打印栈底n层的栈信息
       (gdb) frame <n>           n为一个从0开始证书,栈中的编号,frame 0 表示栈顶 f 1 表示第二层
       (gdb) frame 或 f          查看当前栈的信息
       (gdb) info frame           给出更为详细的当前栈信息
      
       info args   显示出当前函数中所有局部变量及值
       info locals  显示函数中所有局部变量及值
       info catch   显示当前函数中的异常处理信息
      
       查看源程序:
       gdb可以打印出来所调试的源代码,在程序编译时需要加入-g参数。
      
       (gdb) list  <linenum>           打印linenum行的代码
       (gdb) list  <function>          打印function函数的源程序
      
       (gdb) list                            显示当前行后面的源程序
       (gdb) list -                          显示当前行前面的源程序
      
       通过set listsize <count>      设置一次显示的源码行数
       show listsize                        查看当前listsize的设置
      
       (gdb) list <first>, <last>       显示从first行到last行的代码
      
       注:一路list,当到达文件结尾时,再输入list命令出现已经到结尾的提示,使用list num可以将list设置到num行开始显示。
      
       forward-search <regexp>     regexp为正则表达式,前向搜索regexp表达的字符串
       search <regexp>                  regexp为正则表达式,前向搜索regexp表达的字符串
      
       reverse-search <regexp>              反向搜索字符串
      
       搜索字符串时,对于源文件,只编译进了文件名称,没有目录名,可以通过directory进行设置。
       (gdb) directory <dirname …>  可以使用 “:”隔开多个目录名称
       show directories                          显示源文件的搜索路径
      
       info line 可以显示源代码在内存中的地址,info line 后可以跟行号,函数名,文件名:行号,文件名:函数名等。
      
       查看执行中变量内容:
       (gdb) print *array@len                 显示数组的内容
      
       输出格式化
       print  </f>  <expr>                   其中f表示格式字符串
       f取值:
       x 十六进制                  d 十进制                     u 十进制无符号整型
       o 八进制                     t  二进制格式             a 十六进制格式
       c 字符格式                  f  浮点数格式
       如:
       (gdb) p /c i   将i按照字符形式输出
       (gdb) p /f i   将i按照浮点数形式打印出来
      
       examine( 或 x) 查看内存   x /<n/f/u> <addr> 参考前面总结
      
       display <expr>                    自动显示表达式的值
       display /<fmt> <expr>         自动显示表达式的值
       display /<fmt> <expr>         自动显示表达式的值
       expr 为变量或表达式,fmt为格式
      
       undisplay <dnums …>
       delete display <dnums …>  dnums为设置好的自动显示的编号,也即显示表达式的编号,可以通过info display来查看自动显示的信息
      
       disable display <dnums …>
       enalble display <dnums …>  使得显示可用和不可用
      
       设置显示选项:
       set print address
       set print address on   打开地址输出,当程序显示函数信息时,会显示函数的参数地址
       set print address off              关闭函数的参数地址显示
       show print address              查看当前地址显示选项是否打开
      
       同样 array 为显示数组
              elements 显示数组的元素个数信息
              null-stop  遇到结束符时停止显示
              pretty      显示结构体每个元素占一行
              union      显示结构体,是否显示其内的联合体数据
              object      C++对象显示
              static-members 显示静态成员
              vtbl  比较规整的格式来显示虚函数表
 
       改变程序执行:
       修改变量值  x=4 直接修改变量x的值为4
       为了防止和系统的变量冲突,在设置变量值时,加上var 即 set var x= 4
      
       跳转执行:
       jump <linespec>     指定下一个语句的运行点,linespec可以是文件的行号,file:line,可以是+num便宜格式
       jump <address>     address 代表代码行的内存地址
      
       也可以通过 set $pc = 0x456              通过设置pc值来改变程序运行
      
       产生信号量:
       signal <signal>      Linux系统的信号量从1~15,<signal>的取值也在这个范围。
      
       强制返回:
       return
       return <expression>       强制返回一个值,expression
      
       强制调用函数:
       call <expr>     表达式
      
       分析core文件:
       程序执行前,执行$ ulimit –c unlimited  命令,使得自己拥有core dump的权限。
      
       编译程序,直接执行(不要在gdb下执行),出现错误,就可以使用gdb分析core.*文件,看错出现位置。
      
       其中使用 bt命令可以查看栈的情况,使用frame命令(frame statcknum)查看指定栈帧的内容。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值