GDB调试及其调试脚本的使用
2013年04月29日 22:07:20 i龙家小少
请点原文链接:
https://blog.csdn.net/longerzone/article/details/8867790
一、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
-
#include "stdio.h"
-
int main()
-
{
-
int x=3;
-
if(x<4)
-
printf("x is less than 4\n");
-
else
-
printf("x is biger than 4\n");
-
}
程序很简单,设置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调试:
-
#gdb gdbtest <------- 启动GDB
-
GNU gdb (GDB) 7.5-ubuntu
-
Copyright (C) 2012 Free Software Foundation, Inc.
-
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
-
This is free software: you are free to change and redistribute it.
-
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
-
and "show warranty" for details.
-
This GDB was configured as "i686-linux-gnu".
-
For bug reporting instructions, please see:
-
<http://www.gnu.org/software/gdb/bugs/>...
-
Reading symbols from /home/long/gdbtest...done.
-
(gdb) l <------- l命令相当于list,从第一行开始例出原
-
码
-
1 #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 }
-
(gdb) break 5 <------- 设置断点,在源程序第5行处。
-
Breakpoint 1 at 0x8048935: file gdbtest.c, line 5.
-
(gdb) run <------- 运行程序,也可以用简写r
-
Starting program: /home/long/gdbtest
-
Breakpoint 1, main () at gdbtest.c:5 <------- 其实停在第一个断点,在第5行
-
5 if(x<4)
-
(gdb) info break <------- 查看断点的信息
-
Num Type Disp Enb Address What
-
1 breakpoint keep y 0x08048935 in main at gdbtest.c:5
-
breakpoint already hit 1 time
-
(gdb) print x <------- 打印x的值(print 也可以用其简写p)>,这时候x等于上面赋值的3
-
$1 = 3
-
(gdb) print &x <------- 打印x的地址
-
$2 = (int *) 0xbffff21c
-
(gdb) x/4x 0xbffff21c <------- 查看从0xbffff21c开始的4*4个字节的值
-
0xbffff21c: 0x00000003 0x0804a000 0x00000000 0x00000000 <------- x为int值,为4个字节
-
,所以x的值等于0x00000003,我们可以看到此时x等于3
-
(gdb) set x=5 <------- 我们设置x=5
-
(gdb) print x <------- 打印x的值,可以看到x已经被改成5了
-
$3 = 5
-
(gdb) x/4x 0xbffff21c
-
0xbffff21c: 0x00000005 0x0804a000 0x00000000 0x00000000
-
(gdb) n <------- 单条语句执行,next命令简写。
-
8 printf("x is biger than 4\n");
-
(gdb) c <------- 继续运行程序,continue命令简写。
-
Continuing.
-
profiling:/home/zhouyl:Cannot create directory
-
profiling:/home/zhouyl/NicholClass/error_test/gdb/gdbtest.gcda:Skip
-
x is biger than 4[Inferior 1 (process 9265) exited with code 01] <------- 程序输出x is biger than 4,因为此时x已经被改为5了
-
(gdb) q <------- 退出gdb
-
#
在上述GDB调试测试中,我们可以将x的值改为5,然后程序的输出变为 x is biger than 4 。很有趣又很强大是不?
1.3.GDB 更多知识点总结(不断搜集)
1.3.1 GDB 调试如何传参数?
我们仍然使用示例来演示:
示例的代码很简单:test.c
-
#include <stdio.h>
-
int main(int argc, char **argv)
-
{
-
int i=0;
-
i=atoi(argv[1]);
-
i = i + 1;
-
printf("The value after add the first arg is : %d\n",i);
-
i=atoi(argv[2]);
-
i = i - 1;
-
printf("The value after minus the second arg is : %d\n",i);
-
return 0;
-
}
示例中我们分别打印第一个参数加1和第二个参数减1 的值。
我们使用gdb调试,在进入调试后 使用set args 111 1的方法设置参数
-
#gcc -g3 test.c -o test
-
#gdb test <------- 正常开始调剂程序
-
GNU gdb (GDB) 7.5-ubuntu
-
Copyright (C) 2012 Free Software Foundation, Inc.
-
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
-
This is free software: you are free to change and redistribute it.
-
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
-
and "show warranty" for details.
-
This GDB was configured as "i686-linux-gnu".
-
For bug reporting instructions, please see:
-
<http://www.gnu.org/software/gdb/bugs/>...
-
Reading symbols from /tmp/test...done.
-
(gdb) set args 111 1 <------- 在调试时给程序传入参数
-
(gdb) run
-
Starting program: /tmp/test 111 1
-
The value after add the first arg is : 112
-
The value after minus the second arg is : 0
-
[Inferior 1 (process 9667) exited normally]
-
(gdb) q
-
#
或者我们可以使用 gdb --args ./test 111 1的方法
-
gdb --args ./test 111 1
-
GNU gdb (GDB) 7.5-ubuntu
-
Copyright (C) 2012 Free Software Foundation, Inc.
-
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
-
This is free software: you are free to change and redistribute it.
-
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
-
and "show warranty" for details.
-
This GDB was configured as "i686-linux-gnu".
-
For bug reporting instructions, please see:
-
<http://www.gnu.org/software/gdb/bugs/>...
-
Reading symbols from /tmp/test...done.
-
(gdb) run
-
Starting program: /tmp/test 111 1
-
The value after add the first arg is : 112
-
The value after minus the second arg is : 0
-
[Inferior 1 (process 10784) exited normally]
-
(gdb) q
二、GDB调试脚本的使用
下面我们对第一章中的gdbtest.c文件使用gdb脚本调试,其实很简单我们只要把需要的操作放到一个文件中,比如叫做 gdbtest.sh
-
break 5
-
run
-
set x=5
-
c
-
q
那么我们如何使用?其实很简单,我们在使用时,不用直接gdb gdbtest ,而使用 gdb ./gdbtest -command=gdbtest.sh
其实还有种方法,我们直接在脚本中添加所要调试的文件信息,此时的 gdbtest.sh内容为:
-
file gdbtest <----- 制定目标文件为gdbtest
-
break 5
-
run
-
set x=5
-
c
-
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
-
#ls
-
gdbtest.c gdbtest.sh
-
#gcc -g3 -fprofile-arcs -ftest-coverage gdbtest.c <-------- 使用-fprofile-arcs -ftest-coverage 参数添加gcov信息,其实可以不使用-g参数,我示例中需要使用gdb调试,所以添加了
-
#./a.out
-
x is less than 4
-
#gcov gdbtest
-
File‘gdbtest.c’
-
已执行的行数:83.33% (共 6 行)
-
Creating 'gdbtest.c.gcov'
-
# cat gdbtest.c.gcov
-
-: 0:Source:gdbtest.c
-
-: 0:Graph:gdbtest.gcno
-
-: 0:Data:gdbtest.gcda
-
-: 0:Runs:1
-
-: 0:Programs:1
-
-: 1:#include "stdio.h"
-
1: 2:int main() <----------- "1"为本行运行次数
-
-: 3:{
-
1: 4: int x=3;
-
1: 5: if(x<4)
-
1: 6: printf("x is less than 4\n");
-
-: 7: else
-
#####: 8: printf("x is biger than 4\n"); <-----------"#####"代表此行未运>行
-
1: 9:}
-
#
-
#gdb ./a.out -command=gdbtest.sh <-------- 使用上面的脚本调试,其
-
实我们的目的是运行 else ,然后看区别!
-
GNU gdb (GDB) 7.5-ubuntu
-
Copyright (C) 2012 Free Software Foundation, Inc.
-
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
-
This is free software: you are free to change and redistribute it.
-
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
-
and "show warranty" for details.
-
This GDB was configured as "i686-linux-gnu".
-
For bug reporting instructions, please see:
-
<http://www.gnu.org/software/gdb/bugs/>...
-
Reading symbols from /home/long/gcovtest/a.out...done.
-
Breakpoint 1 at 0x80489dd: file gdbtest.c, line 5.
-
Breakpoint 1, main () at gdbtest.c:5
-
5 if(x<4)
-
x is biger than 4
-
[Inferior 1 (process 10165) exited with code 01]
-
#gcov gdbtest <----------- 多运行几次a.out或者
-
使用脚本,后想重新看看最新的测试代码覆盖率,需要重新 gcov gdbtest
-
File‘gdbtest.c’
-
已执行的行数:100.00% (共 6 行)
-
Creating 'gdbtest.c.gcov'
-
#cat gdbtest.c.gcov
-
-: 0:Source:gdbtest.c
-
-: 0:Graph:gdbtest.gcno
-
-: 0:Data:gdbtest.gcda
-
-: 0:Runs:2
-
-: 0:Programs:1
-
-: 1:#include "stdio.h"
-
2: 2:int main()
-
-: 3:{
-
2: 4: int x=3;
-
2: 5: if(x<4)
-
1: 6: printf("x is less than 4\n"); <----------- 使用脚本运行时,此>行未执行,所以还是运行了1次
-
-: 7: else <----------- 其实本行else是运行>过一次的,但是gcov 统计时把本行与下一行打印放在一起计时的!
-
1: 8: printf("x is biger than 4\n");
-
2: 9:}
-
#
注:
【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