gdb调试利器的学习

xiaoxiao2021-02-28  108

本文出自:http://blog.csdn.net/edroid1530/article/details/68946136 作为程序员,调试程序是不可避免的,在windows下常用的IDE比如 keil 软件会有集成的debug图形化调试工具,使用起来非常简单易懂。在Linux下虽然没有图形化调试工具,但是gdb作为文本界面的调试工具其功能也是非常强大的,在这里简单介绍gdb的用法。

一.调试准备

1.首先我们编写一个测试程序:

[cpp] view plain copy print ? [lwn@VM_255_164_centos temp2]vim gdbtest.c  </span></span></li><li><span><span class="comment">/*********************************************************************************</span> </span></li><li class="alt"><span><span class="comment">  2  *      Copyright:  (C) 2017 SCUEC</span> </span></li><li><span><span class="comment">  3  *                  All rights reserved.</span> </span></li><li class="alt"><span><span class="comment">  4  *</span> </span></li><li><span><span class="comment">  5  *       Filename:  gdbtest.c</span> </span></li><li class="alt"><span><span class="comment">  6  *    Description:  This file</span> </span></li><li><span><span class="comment">  7  *</span> </span></li><li class="alt"><span><span class="comment">  8  *        Version:  1.0.0(04/01/17)</span> </span></li><li><span><span class="comment">  9  *         Author:  LI WJNG <liwjng@gmail.com></span> </span></li><li class="alt"><span><span class="comment"> 10  *      ChangeLog:  1, Release initial version on "04/01/17 15:19:12"</span> </span></li><li><span><span class="comment"> 11  *</span> </span></li><li class="alt"><span><span class="comment"> 12  ********************************************************************************/</span><span>  </span></span></li><li><span> 13  </span></li><li class="alt"><span> 14 #include <stdio.h>  </span></li><li><span> 15  </span></li><li class="alt"><span> 16 <span class="datatypes">int</span><span> func(</span><span class="datatypes">int</span><span> n)  </span></span></li><li><span> 17 {  </span></li><li class="alt"><span> 18     <span class="datatypes">int</span><span> sum=0,i;  </span></span></li><li><span> 19     <span class="keyword">for</span><span>(i=0;i<n;i++)  </span></span></li><li class="alt"><span> 20     {  </span></li><li><span> 21         sum += i;  </span></li><li class="alt"><span> 22     }  </span></li><li><span> 23     <span class="keyword">return</span><span> sum;  </span></span></li><li class="alt"><span> 24 }  </span></li><li><span> 25  </span></li><li class="alt"><span> 26  </span></li><li><span> 27 <span class="comment">/********************************************************************************</span> </span></li><li class="alt"><span><span class="comment"> 28  *  Description:</span> </span></li><li><span><span class="comment"> 29  *   Input Args:</span> </span></li><li class="alt"><span><span class="comment"> 30  *  Output Args:</span> </span></li><li><span><span class="comment"> 31  * Return Value:</span> </span></li><li class="alt"><span><span class="comment"> 32  ********************************************************************************/</span><span>  </span></span></li><li><span> 33 <span class="datatypes">int</span><span> main (</span><span class="datatypes">int</span><span> argc, </span><span class="datatypes">char</span><span> **argv)  </span></span></li><li class="alt"><span> 34 {  </span></li><li><span> 35     <span class="datatypes">int</span><span> i;  </span></span></li><li class="alt"><span> 36     <span class="datatypes">long</span><span> result = 0;  </span></span></li><li><span> 37     <span class="datatypes">int</span><span> sum = 0;  </span></span></li><li class="alt"><span> 38     sum  = func(10);  </span></li><li><span> 39     <span class="keyword">for</span><span>(i=0;i<100;i++)  </span></span></li><li class="alt"><span> 40     {  </span></li><li><span> 41         result += i;  </span></li><li class="alt"><span> 42     }  </span></li><li><span> 43  </span></li><li class="alt"><span> 44     printf(<span class="string">"the result is add 1 to 100 is %d\n"</span><span>,result);  </span></span></li><li><span> 45     printf(<span class="string">"the sum is add 1 to %d is %d\n"</span><span>,10,sum);  </span></span></li><li class="alt"><span> 46     <span class="keyword">return</span><span> 0;  </span></span></li><li><span> 47 } <span class="comment">/* ----- End of main() ----- */</span><span>  </span></span></li><li class="alt"><span> 48  </span></li></ol><div class="save_code tracking-ad" style="display: none;" data-mod="popu_249"><a href="javascript:;" target="_blank"><img src="http://static.blog.csdn.net/images/save_snippets.png"></a></div></div><pre class="cpp" style="display: none;" name="code" snippet_file_name="blog_20170401_1_6673937" code_snippet_id="2306771">[lwn@VM_255_164_centos temp2]vim gdbtest.c /********************************************************************************* 2 * Copyright: (C) 2017 SCUEC 3 * All rights reserved. 4 * 5 * Filename: gdbtest.c 6 * Description: This file 7 * 8 * Version: 1.0.0(04/01/17) 9 * Author: LI WJNG <liwjng@gmail.com> 10 * ChangeLog: 1, Release initial version on “04/01/17 15:19:12” 11 * 12 ********************************************************************************/ 13 14 #include <stdio.h> 15 16 int func(int n) 17 { 18 int sum=0,i; 19 for(i=0;i<n;i++) 20 { 21 sum += i; 22 } 23 return sum; 24 } 25 26 27 /******************************************************************************** 28 * Description: 29 * Input Args: 30 * Output Args: 31 * Return Value: 32 ********************************************************************************/ 33 int main (int argc, char **argv) 34 { 35 int i; 36 long result = 0; 37 int sum = 0; 38 sum = func(10); 39 for(i=0;i<100;i++) 40 { 41 result += i; 42 } 43 44 printf(“the result is add 1 to 100 is %d\n”,result); 45 printf(“the sum is add 1 to %d is %d\n”,10,sum); 46 return 0; 47 } /* —– End of main() —– */ 48

2.编译程序

要使用gdb调试,编译的时候一定要加上 -g 选项,如:gcc -g test.c,否则在gdb命令中l的时候会出现:No symbol table is loaded.  Use the “file” command.错误提示;

[cpp] view plain copy print ? [lwn@VM_255_164_centos temp2] gcc -g gdbtest.c -o test  </span></span></li><li><span>[lwn@VM_255_164_centos temp2] ls  gdbtest.c  test   [lwn@VM_255_164_centos temp2]$ gcc -g gdbtest.c -o test [lwn@VM_255_164_centos temp2]$ ls gdbtest.c test

3.使用gdb命令进入调试界面

如果直接使用gdb test 会打印gdb的版本信息等,为了显示简洁一点,使用gdb -q可以不显示版本信息 [cpp] view plain copy print ? [lwn@VM_255_164_centos temp2] gdb -q test  </span></span></li><li><span>Reading symbols from /home/lwn/mysrc/temp2/test...done.  </span></li><li class="alt"><span>(gdb)  </span></li></ol><div class="save_code tracking-ad" data-mod="popu_249"><a href="javascript:;" target="_blank"><img src="http://static.blog.csdn.net/images/save_snippets.png"></a></div></div><pre class="cpp" style="display: none;" name="code" snippet_file_name="blog_20170401_3_1036547" code_snippet_id="2306771">[lwn@VM_255_164_centos temp2] gdb -q test Reading symbols from /home/lwn/mysrc/temp2/test…done. (gdb)

二.gdb调试命令:

在gdb调试界面下可以直接使用gdb的调试命令,enter继续执行上条命令。

下面逐条分析:

1.使用list(简写:l) 命令,将看到部分源程序清单。

list:                显示源程序1-10行 list +行号:      显示行号前后若干行 list +函数名:          显示函数前后若干行 这里就不一一列举了,所有有关list的相关操作可以使用 help list 命令进行查看 如: [cpp] view plain copy print ? (gdb) l main  29       *   Input Args:  30       *  Output Args:  31       * Return Value:  32       ********************************************************************************/  33      int main (int argc, char **argv)  34      {  35          int i;  36          long result = 0;  37          int sum = 0;  38          sum  = func(10);  (gdb) help list //可以看到有关list的命令说明  List specified function or line.  With no argument, lists ten more lines after or around previous listing.  ”list -“ lists the ten lines before a previous ten-line listing.  One argument specifies a line, and ten lines are listed around that line.  Two arguments with comma between specify starting and ending lines to list.  Lines can be specified in these ways:    LINENUM, to list around that line in current file,    FILE:LINENUM, to list around that line in that file,    FUNCTION, to list around beginning of that function,    FILE:FUNCTION, to distinguish among like-named static functions.    *ADDRESS, to list around the line containing that address.  With two args if one is empty it stands for ten lines away from the other arg.   (gdb) l main 29 * Input Args: 30 * Output Args: 31 * Return Value: 32 ********************************************************************************/ 33 int main (int argc, char **argv) 34 { 35 int i; 36 long result = 0; 37 int sum = 0; 38 sum = func(10); (gdb) help list //可以看到有关list的命令说明 List specified function or line. With no argument, lists ten more lines after or around previous listing. "list -" lists the ten lines before a previous ten-line listing. One argument specifies a line, and ten lines are listed around that line. Two arguments with comma between specify starting and ending lines to list. Lines can be specified in these ways: LINENUM, to list around that line in current file, FILE:LINENUM, to list around that line in that file, FUNCTION, to list around beginning of that function, FILE:FUNCTION, to distinguish among like-named static functions. *ADDRESS, to list around the line containing that address. With two args if one is empty it stands for ten lines away from the other arg.

2.运行程序:run(简写:r),break(简写:b) ,continue(简写:c) ,until(简写:u)

  run命令可以让程序全速运行,直到遇到断点处才停下来。如果没有设置断点,那么程序将一直运行到程序结束。   break命令用来设置断点,   break +行号:将断点设置在固定某行   break +函数名:将断点设置在函数开始处   info break:列出所有的断点  clear +行号:取消某行设置的断点   contin命令让程序继续运行到下一处断点,如果后面没有断点将一直运行到程序末尾。    until+行号:让程序执行到固定某行,其作用等同于 break+ 行号,再continu;使用until命令的前提是程序已经在运行状态 例如: [cpp] view plain copy print ? (gdb) l main  29       *   Input Args:  30       *  Output Args:  31       * Return Value:  32       ********************************************************************************/  33      int main (int argc, char **argv)  34      {  35          int i;  36          long result = 0;  37          int sum = 0;  38          sum  = func(10);  (gdb) b main //在main函数开始出设置断点  Breakpoint 1 at 0x40056d: file gdbtest.c, line 36.  (gdb) b 38  //在第38行设置断点  Breakpoint 2 at 0x40057c: file gdbtest.c, line 38.    (gdb) i b //命令info break列出所有的断点  Num     Type           Disp Enb Address            What  1       breakpoint     keep y   0x000000000040056d in main at gdbtest.c:36          breakpoint already hit 1 time  2       breakpoint     keep y   0x000000000040057c in main at gdbtest.c:38          breakpoint already hit 1 time    (gdb) r  //r命令让程序全速运行  Starting program: /home/lwn/mysrc/temp2/test    Breakpoint 1, main (argc=1, argv=0x7fffffffe5c8) at gdbtest.c:36 //遇到刚刚设置的第一个断点36行停了下来  36          long result = 0;  Missing separate debuginfos, use: debuginfo-install glibc-2.17-106.el7_2.8.x86_64  (gdb) c //命令contin让程序继续运行  Continuing.    Breakpoint 2, main (argc=1, argv=0x7fffffffe5c8) at gdbtest.c:38 //运行到设置的第二个断点听了下来  38          sum  = func(10);    (gdb) u 38//让程序执行到固定某一行  main (argc=1, argv=0x7fffffffe5c8) at gdbtest.c:38  38          sum  = func(10);   (gdb) l main 29 * Input Args: 30 * Output Args: 31 * Return Value: 32 ********************************************************************************/ 33 int main (int argc, char **argv) 34 { 35 int i; 36 long result = 0; 37 int sum = 0; 38 sum = func(10); (gdb) b main //在main函数开始出设置断点 Breakpoint 1 at 0x40056d: file gdbtest.c, line 36. (gdb) b 38 //在第38行设置断点 Breakpoint 2 at 0x40057c: file gdbtest.c, line 38. (gdb) i b //命令info break列出所有的断点 Num Type Disp Enb Address What 1 breakpoint keep y 0x000000000040056d in main at gdbtest.c:36 breakpoint already hit 1 time 2 breakpoint keep y 0x000000000040057c in main at gdbtest.c:38 breakpoint already hit 1 time (gdb) r //r命令让程序全速运行 Starting program: /home/lwn/mysrc/temp2/test Breakpoint 1, main (argc=1, argv=0x7fffffffe5c8) at gdbtest.c:36 //遇到刚刚设置的第一个断点36行停了下来 36 long result = 0; Missing separate debuginfos, use: debuginfo-install glibc-2.17-106.el7_2.8.x86_64 (gdb) c //命令contin让程序继续运行 Continuing. Breakpoint 2, main (argc=1, argv=0x7fffffffe5c8) at gdbtest.c:38 //运行到设置的第二个断点听了下来 38 sum = func(10); (gdb) u 38//让程序执行到固定某一行 main (argc=1, argv=0x7fffffffe5c8) at gdbtest.c:38 38 sum = func(10);

3.单步运行next(简写:n) 和step(简写:s) 

如果希望程序逐条语句地执行程序,不停地b、c太过于麻烦,gdb提供了更加step 和next命令,其作用是运行当前行。区别在于如果当前行设计函数调用,next命令会把函数当做一条语句整体执行完毕,而step命令会进入到函数内部继续单步运行,下面来看例子: [cpp] view plain copy print ? l (gdb) l //列出相关行的源程序  31       * Return Value:  32       ********************************************************************************/  33      int main (int argc, char **argv)  34      {  35          int i;  36          long result = 0;  37          int sum = 0;  38          sum  = func(10);  39          for(i=0;i<100;i++)  40          {  (gdb) b 38 //在调用函数的行设置断点  Breakpoint 3 at 0x40057c: file gdbtest.c, line 38.  (gdb) r  The program being debugged has been started already.  Start it from the beginning? (y or n) y  Starting program: /home/lwn/mysrc/temp2/test    Breakpoint 3, main (argc=1, argv=0x7fffffffe5c8) at gdbtest.c:38  38          sum  = func(10);  (gdb) n //可以看到使用next命令之后程序跳到了39行执行  39          for(i=0;i<100;i++)    ————————————————————————————————————————————————————————————————————————————————————————————————————  Breakpoint 3, main (argc=1, argv=0x7fffffffe5c8) at gdbtest.c:38  38          sum  = func(10);  (gdb) s //同样使用step命令之后可以看到程序进入到了func函数去执行  func (n=10) at gdbtest.c:18  18          int sum=0,i;   l (gdb) l //列出相关行的源程序 31 * Return Value: 32 ********************************************************************************/ 33 int main (int argc, char **argv) 34 { 35 int i; 36 long result = 0; 37 int sum = 0; 38 sum = func(10); 39 for(i=0;i<100;i++) 40 { (gdb) b 38 //在调用函数的行设置断点 Breakpoint 3 at 0x40057c: file gdbtest.c, line 38. (gdb) r The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/lwn/mysrc/temp2/test Breakpoint 3, main (argc=1, argv=0x7fffffffe5c8) at gdbtest.c:38 38 sum = func(10); (gdb) n //可以看到使用next命令之后程序跳到了39行执行 39 for(i=0;i<100;i++) ———————————————————————————————————————————————————————————————————————————————————————————————————— Breakpoint 3, main (argc=1, argv=0x7fffffffe5c8) at gdbtest.c:38 38 sum = func(10); (gdb) s //同样使用step命令之后可以看到程序进入到了func函数去执行 func (n=10) at gdbtest.c:18 18 int sum=0,i;

4.打印相关信息info(简写:i),print(简写:p),display(简写:disp)

程序运行到某个位置的时候,我们使用info和print命令可以打印出一些变量的值 info local:打印局部变量的值 p + 变量名:打印该变量的值 display +变量名:每次程序停下来都自动打印该变量的值 来看例子: [cpp] view plain copy print ? (gdb) r  Starting program: /home/lwn/mysrc/temp2/test    Breakpoint 1, main (argc=1, argv=0x7fffffffe5c8) at gdbtest.c:36  36          long result = 0;  Missing separate debuginfos, use: debuginfo-install glibc-2.17-106.el7_2.8.x86_64  (gdb) p result //打印result变量的值  $1 = 140737488348608 //因为第36行语句还没执行,所以现在result还未被初始化,现在是一个垃圾值  (gdb) i lo //打印所有局部变量的值  i = 0  result = 140737488348608  sum = 0  (gdb) disp result //每次遇到程序停下来都将显示变量result的值  1: result = 140737488348608  (gdb) c  Continuing.    Breakpoint 2, main (argc=1, argv=0x7fffffffe5c8) at gdbtest.c:38  38          sum  = func(10);  1: result = 0 //result被初始化为0  (gdb) c  Continuing.    Breakpoint 3, main (argc=1, argv=0x7fffffffe5c8) at gdbtest.c:44  44          printf(”the result is add 1 to 100 is %d\n”,result);  1: result = 4950 //result为最终的计算值   (gdb) r Starting program: /home/lwn/mysrc/temp2/test Breakpoint 1, main (argc=1, argv=0x7fffffffe5c8) at gdbtest.c:36 36 long result = 0; Missing separate debuginfos, use: debuginfo-install glibc-2.17-106.el7_2.8.x86_64 (gdb) p result //打印result变量的值 $1 = 140737488348608 //因为第36行语句还没执行,所以现在result还未被初始化,现在是一个垃圾值 (gdb) i lo //打印所有局部变量的值 i = 0 result = 140737488348608 sum = 0 (gdb) disp result //每次遇到程序停下来都将显示变量result的值 1: result = 140737488348608 (gdb) c Continuing. Breakpoint 2, main (argc=1, argv=0x7fffffffe5c8) at gdbtest.c:38 38 sum = func(10); 1: result = 0 //result被初始化为0 (gdb) c Continuing. Breakpoint 3, main (argc=1, argv=0x7fffffffe5c8) at gdbtest.c:44 44 printf("the result is add 1 to 100 is %d\n",result); 1: result = 4950 //result为最终的计算值

5.条件控制断点

在for循环中,有时候我们想让循环变量i为某个固定值的时候停下来查看某一变量,如果一直单步运行工作量有可能会很大。gdb提供了一个命令cond命令 话不多说,来看例子: [cpp] view plain copy print ? 39  for(i=0;i<100;i++)   40         {   41             result += i;   42         }   39 for(i=0;i<100;i++) 40 { 41 result += i; 42 } 在这个循环中,当i=10的时候我想看看result的值怎么办呢?很好办,往下看 首先在41行设置断点,然后使用cond 2 i==10 [cpp] view plain copy print ? (gdb) b 41 //在41行设置断点  Breakpoint 1 at 0x400592: file gdbtest.c, line 41.  (gdb) cond 1 i==10 //当i等于10的时候程序停下来  (gdb) r  Starting program: /home/lwn/mysrc/temp2/test    Breakpoint 1, main (argc=1, argv=0x7fffffffe5c8) at gdbtest.c:41  41              result += i;  (gdb) p i  1 = 10  </span></li><li class="alt"><span>(gdb) p result<span class="comment">//可以看到当i=10的时候 result 的值为45</span><span>  </span></span></li><li><span>2 = 45   (gdb) b 41 //在41行设置断点 Breakpoint 1 at 0x400592: file gdbtest.c, line 41. (gdb) cond 1 i==10 //当i等于10的时候程序停下来 (gdb) r Starting program: /home/lwn/mysrc/temp2/test Breakpoint 1, main (argc=1, argv=0x7fffffffe5c8) at gdbtest.c:41 41 result += i; (gdb) p i $1 = 10 (gdb) p result//可以看到当i=10的时候 result 的值为45 $2 = 45 在大多数情况下,灵活使用这些命令已经能够高效的调试程序了,如果对于这些gdb命令还有疑问的可以使用help命令获得详细的帮助信息。

转载请注明原文地址: https://www.6miu.com/read-68594.html

最新回复(0)