GDB调试及其调试脚本的使用

一、GDB调试

1.1. GDB 概述

GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具。或许,各位比较喜欢那种图形界面方式的,像VC、BCB等IDE的调试,但如果你是在UNIX/Linux平台下做软件,你会发现GDB这个调试工具有比VC、BCB的图形化调试器更强大的功能。所谓“寸有所长,尺有所短”就是这个道理。

一般来说,GDB主要帮忙你完成下面四个方面的功能:

    1、启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。
    2、可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式)
    3、当程序被停住时,可以检查此时你的程序中所发生的事。
    4、动态的改变你程序的执行环境。

从上面看来,GDB和一般的调试工具没有什么两样,基本上也是完成这些功能,不过在细节上,你会发现GDB这个调试工具的强大,大家可能比较习惯了图形化的调试工具,但有时候,命令行的调试工具却有着图形化工具所不能完成的功能。让我们一一看来。


1.2.GDB 使用示例

使用一个简单的判断来测试一下:文件名gdbtest.c

[cpp] view plaincopy
  1. <span style="font-size:18px">#include "stdio.h"  
  2. int main()  
  3. {  
  4.     int x=3;  
  5.     if(x<4)  
  6.         printf("x is less than 4\n");  
  7.     else   
  8.         printf("x is biger than 4\n");  
  9. }  
  10. </span>  


程序很简单,设置x=3,然后判断x是否比4小,若比4小则输出”x is less than 4“,若比4大,则输出”x is biger than 4“ ,程序很无聊,但是我们可以用来做GDB的测试!

注: 编译的时候需要使用-g选项,我使用的是:  gdb -g3 gdbtest.c -o gdbtest

使用GDB调试:

[cpp] view plaincopy
  1. #gdb gdbtest                                <------- 启动GDB  
  2. GNU gdb (GDB) 7.5-ubuntu  
  3. Copyright (C) 2012 Free Software Foundation, Inc.  
  4. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>  
  5. This is free software: you are free to change and redistribute it.  
  6. There is NO WARRANTY, to the extent permitted by law.  Type "show copying"  
  7. and "show warranty" for details.  
  8. This GDB was configured as "i686-linux-gnu".  
  9. For bug reporting instructions, please see:  
  10. <http://www.gnu.org/software/gdb/bugs/>...  
  11. Reading symbols from /home/long/gdbtest...done.  
  12. (gdb) l                                     <------- l命令相当于list,从第一行开始例出原  
  13. 码  
  14. 1   #include "stdio.h"  
  15. 2   int main()  
  16. 3   {  
  17. 4       int x=3;  
  18. 5       if(x<4)  
  19. 6           printf("x is less than 4\n");  
  20. 7       else  
  21. 8           printf("x is biger than 4\n");  
  22. 9   }  
  23. (gdb) break 5                               <------- 设置断点,在源程序第5行处。  
  24. Breakpoint 1 at 0x8048935: file gdbtest.c, line 5.  
  25. (gdb) run                                   <------- 运行程序,也可以用简写r  
  26. Starting program: /home/long/gdbtest  
  27.   
  28. Breakpoint 1, main () at gdbtest.c:5        <------- 其实停在第一个断点,在第5行  
  29. 5       if(x<4)  
  30. (gdb) info break                            <------- 查看断点的信息  
  31. Num     Type           Disp Enb Address    What  
  32. 1       breakpoint     keep y   0x08048935 in main at gdbtest.c:5  
  33.     breakpoint already hit 1 time  
  34. (gdb) print x                               <------- 打印x的值(print 也可以用其简写p)>,这时候x等于上面赋值的3  
  35. $1 = 3  
  36. (gdb) print &x                              <------- 打印x的地址  
  37. $2 = (int *) 0xbffff21c  
  38. (gdb) x/4x 0xbffff21c                       <------- 查看从0xbffff21c开始的4*4个字节的值  
  39. 0xbffff21c: 0x00000003  0x0804a000  0x00000000  0x00000000  <------- x为int值,为4个字节  
  40. ,所以x的值等于0x00000003,我们可以看到此时x等于3  
  41. (gdb) set x=5                               <------- 我们设置x=5  
  42. (gdb) print x                               <------- 打印x的值,可以看到x已经被改成5了  
  43. $3 = 5  
  44. (gdb) x/4x 0xbffff21c  
  45. 0xbffff21c: 0x00000005  0x0804a000  0x00000000  0x00000000  
  46. (gdb) n                                     <------- 单条语句执行,next命令简写。  
  47. 8           printf("x is biger than 4\n");  
  48. (gdb) c                                     <------- 继续运行程序,continue命令简写。  
  49. Continuing.                                   
  50. profiling:/home/zhouyl:Cannot create directory  
  51. profiling:/home/zhouyl/NicholClass/error_test/gdb/gdbtest.gcda:Skip  
  52. x is biger than 4[Inferior 1 (process 9265) exited with code 01]    <------- 程序输出x is biger than 4,因为此时x已经被改为5了  
  53. (gdb) q                                     <-------  退出gdb  
  54. #  


在上述GDB调试测试中,我们可以将x的值改为5,然后程序的输出变为 x is biger than 4 。很有趣又很强大是不?


1.3.GDB 更多知识点总结(不断搜集)

1.3.1 GDB 调试如何传参数?

我们仍然使用示例来演示:

示例的代码很简单:test.c

[cpp] view plaincopy
  1. #include <stdio.h>  
  2. int main(int argc, char **argv)  
  3. {  
  4.     int i=0;  
  5.     i=atoi(argv[1]);  
  6.     i = i + 1;  
  7.     printf("The value after add the first arg is : %d\n",i);  
  8.     i=atoi(argv[2]);  
  9.     i = i - 1;  
  10.     printf("The value after minus the second arg is : %d\n",i);  
  11.     return 0;  
  12. }  


示例中我们分别打印第一个参数加1和第二个参数减1 的值。

我们使用gdb调试,在进入调试后 使用set args  111  1的方法设置参数

[cpp] view plaincopy
  1. #gcc -g3 test.c -o test  
  2. #gdb test                                   <------- 正常开始调剂程序  
  3. GNU gdb (GDB) 7.5-ubuntu  
  4. Copyright (C) 2012 Free Software Foundation, Inc.  
  5. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>  
  6. This is free software: you are free to change and redistribute it.  
  7. There is NO WARRANTY, to the extent permitted by law.  Type "show copying"  
  8. and "show warranty" for details.  
  9. This GDB was configured as "i686-linux-gnu".  
  10. For bug reporting instructions, please see:  
  11. <http://www.gnu.org/software/gdb/bugs/>...  
  12. Reading symbols from /tmp/test...done.  
  13. (gdb) set args 111  1                       <------- 在调试时给程序传入参数  
  14. (gdb) run  
  15. Starting program: /tmp/test 111  1  
  16. The value after add the first arg is : 112  
  17. The value after minus the second arg is : 0  
  18. [Inferior 1 (process 9667) exited normally]  
  19. (gdb) q  
  20. #  


或者我们可以使用 gdb  --args  ./test  111  1的方法

[cpp] view plaincopy
  1. gdb --args ./test 111 1  
  2. GNU gdb (GDB) 7.5-ubuntu  
  3. Copyright (C) 2012 Free Software Foundation, Inc.  
  4. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>  
  5. This is free software: you are free to change and redistribute it.  
  6. There is NO WARRANTY, to the extent permitted by law.  Type "show copying"  
  7. and "show warranty" for details.  
  8. This GDB was configured as "i686-linux-gnu".  
  9. For bug reporting instructions, please see:  
  10. <http://www.gnu.org/software/gdb/bugs/>...  
  11. Reading symbols from /tmp/test...done.  
  12. (gdb) run  
  13. Starting program: /tmp/test 111 1  
  14. The value after add the first arg is : 112  
  15. The value after minus the second arg is : 0  
  16. [Inferior 1 (process 10784) exited normally]  
  17. (gdb) q  



二、GDB调试脚本的使用

下面我们对第一章中的gdbtest.c文件使用gdb脚本调试,其实很简单我们只要把需要的操作放到一个文件中,比如叫做 gdbtest.sh

[cpp] view plaincopy
  1. break 5  
  2. run  
  3. set x=5  
  4. c  
  5. q  

那么我们如何使用?其实很简单,我们在使用时,不用直接gdb gdbtest ,而使用   gdb  ./gdbtest  -command=gdbtest.sh

其实还有种方法,我们直接在脚本中添加所要调试的文件信息,此时的  gdbtest.sh内容为:

[cpp] view plaincopy
  1. file gdbtest            <----- 制定目标文件为gdbtest  
  2. break 5  
  3. run  
  4. set x=5  
  5. c  
  6. q  

而我们调试使用的命令就简单了,直接使用 gdb -x gdbtest.sh  即可!



三、GCOV的使用

3.1  gcov是什么?

  • Gcov is GCC Coverage
  • 是一个测试代码覆盖率的工具
  • 是一个命令行方式的控制台程序
  • 伴随GCC发布配合GCC共同实现对C/C++文件的语句覆盖和分支覆盖测试
  • 与程序概要分析工具(profiling tool,例如gprof)一起工作,可以估计程序中哪一段代码最耗时;

注:程序概要分析工具是分析代码性能的工具。


3.2  gcov能做什么?

 gcov可以统计:

  • 每一行代码的执行频率
  • 实际上哪些代码确实被执行了
  • 每一段代码(section code)的耗时(执行时间)

因此,gcov可以帮你优化代码,当然这个优化动作还是应该有开发者完成。


3.3 gcov 使用

我们继续使用第一章中的gdbtest.c文件,使用gcov时候,在编译时使用  gcc -g3 -fprofile-arcs -ftest-coverage gdbtest.c

[cpp] view plaincopy
  1. <span style="font-size:18px">#ls  
  2. gdbtest.c  gdbtest.sh  
  3. #gcc -g3 -fprofile-arcs -ftest-coverage gdbtest.c       <-------- 使用-fprofile-arcs -ftest-coverage 参数添加gcov信息,其实可以不使用-g参数,我示例中需要使用gdb调试,所以添加了  
  4. #./a.out  
  5. x is less than 4  
  6. #gcov gdbtest  
  7. File‘gdbtest.c’  
  8. 已执行的行数:83.33% (共 6 行)  
  9. Creating 'gdbtest.c.gcov'  
  10.   
  11. # cat gdbtest.c.gcov  
  12.         -:    0:Source:gdbtest.c  
  13.         -:    0:Graph:gdbtest.gcno  
  14.         -:    0:Data:gdbtest.gcda  
  15.         -:    0:Runs:1  
  16.         -:    0:Programs:1  
  17.         -:    1:#include "stdio.h"  
  18.         1:    2:int main()                              <----------- "1"为本行运行次数  
  19.         -:    3:{  
  20.         1:    4:    int x=3;  
  21.         1:    5:    if(x<4)  
  22.         1:    6:        printf("x is less than 4\n");  
  23.         -:    7:    else   
  24.     #####:    8:        printf("x is biger than 4\n");  <-----------"#####"代表此行未运>行    
  25.         1:    9:}  
  26. #         
  27. #gdb ./a.out -command=gdbtest.sh                        <-------- 使用上面的脚本调试,其  
  28. 实我们的目的是运行 else ,然后看区别!  
  29. GNU gdb (GDB) 7.5-ubuntu  
  30. Copyright (C) 2012 Free Software Foundation, Inc.  
  31. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>  
  32. This is free software: you are free to change and redistribute it.  
  33. There is NO WARRANTY, to the extent permitted by law.  Type "show copying"  
  34. and "show warranty" for details.  
  35. This GDB was configured as "i686-linux-gnu".  
  36. For bug reporting instructions, please see:  
  37. <http://www.gnu.org/software/gdb/bugs/>...  
  38. Reading symbols from /home/long/gcovtest/a.out...done.  
  39. Breakpoint 1 at 0x80489dd: file gdbtest.c, line 5.  
  40. Breakpoint 1, main () at gdbtest.c:5  
  41. 5       if(x<4)  
  42. x is biger than 4  
  43. [Inferior 1 (process 10165) exited with code 01]  
  44. #gcov gdbtest                                           <----------- 多运行几次a.out或者  
  45. 使用脚本,后想重新看看最新的测试代码覆盖率,需要重新 gcov gdbtest  
  46. File‘gdbtest.c’   
  47. 已执行的行数:100.00% (共 6 行)  
  48. Creating 'gdbtest.c.gcov'   
  49. #cat gdbtest.c.gcov  
  50.         -:    0:Source:gdbtest.c  
  51.         -:    0:Graph:gdbtest.gcno  
  52.         -:    0:Data:gdbtest.gcda  
  53.         -:    0:Runs:2  
  54.         -:    0:Programs:1  
  55.         -:    1:#include "stdio.h"  
  56.         2:    2:int main()  
  57.         -:    3:{  
  58.         2:    4:    int x=3;  
  59.         2:    5:    if(x<4)  
  60.         1:    6:        printf("x is less than 4\n");   <----------- 使用脚本运行时,此>行未执行,所以还是运行了1次  
  61.         -:    7:    else                                <----------- 其实本行else是运行>过一次的,但是gcov 统计时把本行与下一行打印放在一起计时的!  
  62.         1:    8:        printf("x is biger than 4\n");  
  63.         2:    9:}  
  64. #  
  65. </span>  




注: 

【1】陈浩专栏: "用GDB调试工具"

一、 http://blog.csdn.net/haoel/article/details/2879

二、http://blog.csdn.net/haoel/article/details/2880

三、http://blog.csdn.net/haoel/article/details/2881

四、http://blog.csdn.net/haoel/article/details/2882

五、http://blog.csdn.net/haoel/article/details/2883

六、http://blog.csdn.net/haoel/article/details/2884

七、http://blog.csdn.net/haoel/article/details/2885

【2】http://blog.csdn.net/zhujinghao09/article/details/8461543

【3】http://blog.csdn.net/ganggexiongqi/article/details/8846001

【4】http://blog.csdn.net/yukin_xue/article/details/7653482

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/351082.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python中xlrd模块解析

xlrd 导入模块 import xlrd 2、打开指定的excel文件&#xff0c;返回一个data对象 data xlrd.open_workbook(file) #打开excel表&#xff0c;返回data对象 3、通过data对象可以得到各个sheet对象(一个excel文件可以有多个sheet&#xff0c;每个sheet就是一…

数学中常见的距离

1. 欧氏距离 最常见的两点之间或多点之间的距离表示法&#xff0c;又称之为欧几里得度量&#xff0c;它定义于欧几里得空间中&#xff0c;如点 x (x1,...,xn) 和 y (y1,...,yn) 之间的距离为&#xff1a; (1) 二维平面上两点a(x1,y1)与b(x2,y2)间的欧氏距离&#xff1a; (…

使用Spring Boot和Heroku在20分钟内完成Java的单点登录

建筑物身份管理&#xff0c;包括身份验证和授权&#xff1f; 尝试Stormpath&#xff01; 我们的REST API和强大的Java SDK支持可以消除您的安全风险&#xff0c;并且可以在几分钟内实现。 注册 &#xff0c;再也不会建立auth了&#xff01; 大规模更新 我最初为本文撰写的代码…

OO第一次单元总结

第一次总结性博客 16071070 陈泽寅 2019.3.23 一、第一单元所学总结 首先先来总结一下第一单元我所学到的知识以及所感所悟。第一个单元&#xff0c;是我第一次接触JAVA语言&#xff0c;并且再使用了几次之后&#xff0c;就被这门语言的独有的魅力以及简便的用法所深深吸引。下…

汇编语言学习笔记(十二)-浮点指令

浮点数如何存储浮点寄存器浮点数指令浮点计算例子浮点高级运算CMOV移动指令 浮点数如何存储 浮点数的运算完全不同于整数&#xff0c;从寄存器到指令&#xff0c;都有一套独特的处理流程&#xff0c;浮点单元也称作x87 FPU。 现在看浮点数的表示方式&#xff0c;我们所知道的&a…

人工智能简述

人工智能研究的方向之一&#xff0c;是以所谓 “专家系统” 为代表的&#xff0c;用大量 “如果-就” &#xff08;If - Then&#xff09; 规则定义的&#xff0c;自上而下的思路。   人工神经网络 &#xff08; Artifical Neural Network&#xff09;&#xff0c;标志着另外…

Mockito 的使用

转自&#xff1a;Mockito 中文文档 ( 2.0.26 beta ) 转自&#xff1a;手把手教你 Mockito 的使用 参数匹配器 Argument Matcher(参数匹配器) Mockito通过equals()方法&#xff0c;来对方法参数进行验证。但是有时候我们需要更加灵活的参数需求&#xff0c;比如&#xff0c;匹配…

以SYSTEM用户运行CMD

在SCCM 经常会以NT AUTHOR\SYSTEM帐户操作。 安以下步骤可以以SYSTEM帐户打开一个CMD窗口。 1. 从微软网站下载PSTool。 2. 以管理员运行CMD&#xff0c;进入到解压的PSTool目录。 3. 运行psexec -i -s cmd.exe 4. 在新打开的CMD中运行whoami。 注&#xff1a;这个指令可以让你…

matlab cell

如果p为一个数&#xff0c;那么h(1)p,是没有问题的。 如果p为一个向量&#xff0c;那么h(1,:)p是没有问题的。 如果p是一个矩阵的话&#xff0c;上面的两种赋值方法都是会有错误的。 那么要如何处理呢&#xff1f; 这时就用到了cell数据类型了。cell的每个单元都可以存储任何数…

jboss 不适用内置日志_适用于孩子,父母和祖父母的JBoss HornetQ –第1章

jboss 不适用内置日志现在与HornetQ合作已经快4年了&#xff0c;我认为现在该分享我到目前为止所学的部分知识了。 这篇文章的主要目的不是重写官方文档 &#xff0c;而是以简单的方式阐明我们在PaddyPower中最常用的概念。 什么是HornetQ HornetQ是JMS实现。 JMS是一种面向…

Spring Cloud微服务笔记(四)客户端负载均衡:Spring Cloud Ribbon

客户端负载均衡&#xff1a;Spring Cloud Ribbon 一、负载均衡概念 负载均衡在系统架构中是一个非常重要&#xff0c;并且是不得不去实施的内容。因为负载均衡对系统的高可用性、 网络压力的缓解和处理能力的扩容的重要手段之一。通常所说的负载均衡指的是服务端负载均衡&#…

matlab cell,fix,floor,round取整的几种方式

ceil函数的作用是朝正无穷方向取整&#xff0c;即将m/n的结果向正无穷方向取整&#xff0c;如m/n3.12&#xff0c;则ceil(m/n)的结果为4。 类似的函数有如下几个&#xff1a; fix&#xff1a;朝零方向取整&#xff0c;如fix(-1.3)-1;fix(1.3)1; floor&#xff1a;朝负无穷方…

孤儿进程与僵尸进程[总结]

1、前言 之前在看《unix环境高级编程》第八章进程时候&#xff0c;提到孤儿进程和僵尸进程&#xff0c;一直对这两个概念比较模糊。今天被人问到什么是孤儿进程和僵尸进程&#xff0c;会带来什么问题&#xff0c;怎么解决&#xff0c;我只停留在概念上面&#xff0c;没有深入&a…

使用CloudForms实现云运营幸福感的3个步骤

本周宣布&#xff0c; Cloud Suite管理层的最新功能 CloudForms 4.2可供所有人使用。 产品增加了1800多种改进&#xff0c;令许多令人兴奋的新奇事物令人兴奋。 CloudForms是Cloud Suite产品的Cloud Management平台&#xff0c;使您能够跨区域联合部署它以进行集中管理操作&am…

leetcode 599. 两个列表的最小索引总和(Minimum Index Sum of Two Lists)

目录 题目描述&#xff1a;示例 1:示例 2:解法&#xff1a;题目描述&#xff1a; 假设Andy和Doris想在晚餐时选择一家餐厅&#xff0c;并且他们都有一个表示最喜爱餐厅的列表&#xff0c;每个餐厅的名字用字符串表示。 你需要帮助他们用最少的索引和找出他们共同喜爱的餐厅。 如…

FAR,FRR,EER

FRR与FARFRR&#xff08;False Rejection Rate&#xff09;和FAR&#xff08;False Acceptance Rate&#xff09;是用来评估指纹识别算法性能的两个主要参数。FRR和FAR有时被用来评价一个指纹识别系统的性能&#xff0c;其实这并不贴切。指纹识别系统的性能除了受指纹算法的影响…

通过一段汇编,加深对寄存器ESP和EBP的理解

一直对寄存器ESP和EBP的概念总是有些混淆&#xff0c;查看定义ESP是栈顶指针&#xff0c;EBP是存取堆栈指针。还是不能很透彻理解。之后借于一段汇编代码&#xff0c;总算是对两者有个比较清晰的理解。下面是按调用约定__stdcall 调用函数test(int p1,int p2)的汇编代码;假设执…

Redis和数据库 数据同步问题

Redis和数据库同步问题缓存充当数据库比如说Session这种访问非常频繁的数据&#xff0c;就适合采用这种方案&#xff1b;当然了&#xff0c;既然没有涉及到数据库&#xff0c;那么也就不会存在一致性问题&#xff1b;缓存充当数据库热点缓存读操作目前的读操作有个固定的套路&a…

matlab fspecial创建滤波算子

Fspecial函数用于创建预定义的滤波算子&#xff0c;其语法格式为&#xff1a;h fspecial(type) h fspecial(type,parameters,sigma)参数type制定算子类型&#xff0c;parameters指定相应的参数&#xff0c;具体格式为&#xff1a;typeaverage&#xff0c;为均值滤波&#xff…

hibernate jpa_JPA / Hibernate:基于版本的乐观并发控制

hibernate jpa本文是对Hibernate和JPA中基于版本的乐观并发控制的介绍。 这个概念已经很老了&#xff0c;上面已经写了很多东西&#xff0c;但是无论如何我都看到了它被重新发明&#xff0c;误解和滥用。 我在写它只是为了传播知识&#xff0c;并希望引起对并发控制和锁定的兴趣…