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系统的信号量从115<signal>的取值也在这个范围。

      

       强制返回:

       return

       return <expression>       强制返回一个值,expression

      

       强制调用函数:

       call <expr>     表达式

      

       分析core文件:

       程序执行前,执行$ ulimit –c unlimited  命令,使得自己拥有core dump的权限。

      

       编译程序,直接执行(不要在gdb下执行),出现错误,就可以使用gdb分析core.*文件,看错出现位置。

      

       其中使用 bt命令可以查看栈的情况,使用frame命令(frame statcknum)查看指定栈帧的内容。

 

By Andy @ 2012-07-12 17:06

你可能感兴趣的:(编程,c,linux,list,input,工具)