GDB三方面的功能:
1、启动被调试程序
2、让被调试的程序在指定的位置挺住
3、当程序被停住时,可以检查程序状态
现在让我们就实例进行对gdb功能的了解:
创建一个demo.c,写如下程序:
#include<stdio.h>
int add_sum(int sum)
{
int temp = 15;
sum = sum + temp;
return sum;
}
int main()
{
int sum = 0;
int i;
for(i = 0;i <= 100;i++)
{
sum = sum + i;
}
printf("sum = %d\n",sum);
int result = add_sum(sum);
printf("result = %d\n",result);
return 0;
}
下面对demo.c进行编译
gcc -g demo.c -o demo
gdb demo(GDB会显示版本信息,然后停在符号(gdb)处等待用户输入调试命令)
(gdb)run(运行程序)
(gdb)list(查看源文件)
(gdb)break(在20行设置断点)
(gdb)info break(查看断点情况,有断点编号)
(gdb)delete +断点编号(删除断点)
(gdb)print i(查看当前i的值)
(gdb)continue(断点后继续运行)
(gdb)next(单步运行 next不会进入函数内部运行)
(gdb)step(单步运行 step可以进入函数内部运行)
调试器GDB其实有个非常妙的用处:它可以用来处理段错误(即在编译时没有错,运行却显示错误)
示例代码demo.c:
#include<stdio.h>
int main()
{
char *ptr = "hello world!";
ptr++;
*ptr = 'L';//此处有错误 但编译时不会显示此错误
printf("ptr = %s\n",ptr);
return 0;
}
用gdb调试:
gcc -g demo.c
gdb a,out
(gdb)run(停在哪一行,就是哪一行段错误)
其实 还有一个检测段错误的方法 就是每行打印有个标记 停在哪哪里就有错
如:
#include<stdio.h>
int main()
{
char *ptr = "hello world!";
printf("A!\n");
ptr++;
printf("B!\n");
*ptr = 'L';
printf("C!\n");
printf("ptr = %s\n",ptr);
printf("D!\n");
return 0;
}
这样的打印结果为:A! B!我们就可以知道错误在*ptr = 'L';啦~
但是如果开发一款软件,代码量巨大 ,而且也不能显示给用户你的调试信息,同时为了便于程序员检错,那么这就需要宏替换这一神器啦~ 编写一个头文件debug.h #ifndef __DEBUG__#define debug_msg(fmt, args...)
#else
#define debug_msg(fmt, args...) printf(fmt, ##args) //将debug_msg替换成printf
#endif
发布版将头文件第一行删掉 同时检错代码改为:
#include<stdio.h>
int main()
{
char *ptr = "hello world!";
debug_msg("A!\n");
ptr++;
debug_msg("B!\n");
*ptr = 'L';
debug_msg("C!\n");
printf("ptr = %s\n",ptr);
debug"D!\n");
return 0;
}
而程序需要检错时只要在编译时输入:gcc demo.c -D__DEBUG__(注意是两个_)这就相当于在头文件第一行加了#define__DEBUG__
调试器GDB就讲完啦~~