今天学习了linux环境下gdb调试工具的使用,在英语半通不通的情况下,终于琢磨出来了它的使用方法。
gdb包含以下一些功能:
1.监视程序中变量的值
2.设置断点以使程序在指定的代码行上停止执行(以前我们总是设置输出1或者其他什么的测试)
3.一行行地执行代码
首先我们要先检查我们的linux系统有没有装gdb这个工具
在命令框中直接输入gdb就可以查看有没有装
这是装好了的显示结果,如果没有装,会提示你怎么装
这里用gdb调试一个输出一个字符串以及把它反序输出的c程序
源代码如下:
#include<stdio.h>
#include <string.h>
#include <stdlib.h>
void print1(char *string)
{
printf("The string is %s\n",string);
}
void print2(char *string)
{
char *string2;
int size,i;
size=strlen(string);
string2=(char *)malloc(size+1);
for(i=0;i<size;i++)
string2[size-i]=string[i];
string2[size+1]='\0';
printf("The string printed backward is:%s\n",string2);
}
main()
{
char test_string[]="Hello World";
print1(test_string);
print2(test_string);
}
将它保存为1.c
然后用gcc编译,但这里要加入一个选项:-g
gcc 1.c -g
这样编译生成的文件名是a.out,若想改变生成文件的名用如下格式:
gcc 1.c -g -o 1
./a.out(./1) 一下,可以看到输出结果是:
The string is Hello World
The string printed backward is:
反序输出并没有显示出来,所以要用到gdb调试程序
输入下面的语句:
gdb a.out(gdb 1)
会出现下面的显示
输入run
,让它运行一下,会输出和刚才运行结果一样的结果
list 1
,从第一行开始把程序列出来,默认显示10行,只要连续再按几个回车就可以全部显示
1 /*************************************************************************
2 > File Name: 1.c
3 > Author:
4 > Mail:
5 > Created Time: 2016年04月15日 星期五 21时34分27秒
6 ************************************************************************/
7
8 #include<stdio.h>
9 #include <string.h>
10 #include <stdlib.h>
(gdb)
11 void print1(char *string)
12 {
13 printf("The string is %s\n",string);
14
15 }
16 void print2(char *string)
17 {
18 char *string2;
19 int size,i;
20 size=strlen(string);
(gdb)
21 string2=(char *)malloc(size+1);
22 for(i=0;i<size;i++)
23 string2[size-i]=string[i];
24 string2[size+1]='\0';
25 printf("The string printed backward is:%s\n",string2);
26 }
27 main()
28 {
29 char test_string[]="Hello World";
30 print1(test_string);
(gdb)
31 print2(test_string);
32 }
(gdb)
Line number 33 out of range; 1.c has 32 lines.
从输出结果看,应该是给第二个字符串赋值的时候出现了问题,所以我们在for语句行里赋值的过程中设置断点
输入 break 223
,再输入run
时,会出现
Breakpoint 1, print2 (string=0x7fffffffdf30 "Hello World") at 1.c:23
23 string2[size-i]=string[i];
我们需要查看每一次循环赋给string2
的值,所以用diplay
命令,依次输入display size-i
,display i
,display string2[size-i]
,后面输入直接输入next就可以查看它们的值,也可以按向上的键,重复上一条命令,直到找到问题并改正。
(gdb) display size-i
1: size-i = 11
(gdb) display i
2: i = 0
(gdb) display string2[size-i]
3: string2[size-i] = 0 '\000'
(gdb) next
22 for(i=0;i<size;i++)
3: string2[size-i] = 72 'H'
2: i = 0
1: size-i = 11
(gdb) next
Breakpoint 1, print2 (string=0x7fffffffdf30 "Hello World") at 1.c:23
23 string2[size-i]=string[i];
3: string2[size-i] = 0 '\000'
2: i = 1
1: size-i = 10
(gdb) next
22 for(i=0;i<size;i++)
3: string2[size-i] = 101 'e'
2: i = 1
1: size-i = 10
(gdb) next
Breakpoint 1, print2 (string=0x7fffffffdf30 "Hello World") at 1.c:23
23 string2[size-i]=string[i];
3: string2[size-i] = 0 '\000'
2: i = 2
1: size-i = 9
(gdb) next
22 for(i=0;i<size;i++)
3: string2[size-i] = 108 'l'
2: i = 2
1: size-i = 9
(gdb) next
Breakpoint 1, print2 (string=0x7fffffffdf30 "Hello World") at 1.c:23
23 string2[size-i]=string[i];
3: string2[size-i] = 0 '\000'
2: i = 3
1: size-i = 8
(gdb) next
22 for(i=0;i<size;i++)
3: string2[size-i] = 108 'l'
2: i = 3
1: size-i = 8
(gdb) next
Breakpoint 1, print2 (string=0x7fffffffdf30 "Hello World") at 1.c:23
23 string2[size-i]=string[i];
3: string2[size-i] = 0 '\000'
2: i = 4
1: size-i = 7
(gdb) next
22 for(i=0;i<size;i++)
3: string2[size-i] = 111 'o'
2: i = 4
1: size-i = 7
(gdb) next
Breakpoint 1, print2 (string=0x7fffffffdf30 "Hello World") at 1.c:23
23 string2[size-i]=string[i];
3: string2[size-i] = 0 '\000'
2: i = 5
1: size-i = 6
(gdb) next
22 for(i=0;i<size;i++)
3: string2[size-i] = 32 ' '
2: i = 5
1: size-i = 6
(gdb) next
Breakpoint 1, print2 (string=0x7fffffffdf30 "Hello World") at 1.c:23
23 string2[size-i]=string[i];
3: string2[size-i] = 0 '\000'
2: i = 6
1: size-i = 5
(gdb) next
22 for(i=0;i<size;i++)
3: string2[size-i] = 87 'W'
2: i = 6
1: size-i = 5
(gdb) next
Breakpoint 1, print2 (string=0x7fffffffdf30 "Hello World") at 1.c:23
23 string2[size-i]=string[i];
3: string2[size-i] = 0 '\000'
2: i = 7
1: size-i = 4
(gdb) next
22 for(i=0;i<size;i++)
3: string2[size-i] = 111 'o'
2: i = 7
1: size-i = 4
(gdb) next
Breakpoint 1, print2 (string=0x7fffffffdf30 "Hello World") at 1.c:23
23 string2[size-i]=string[i];
3: string2[size-i] = 0 '\000'
2: i = 8
1: size-i = 3
(gdb) next
22 for(i=0;i<size;i++)
3: string2[size-i] = 114 'r'
2: i = 8
1: size-i = 3
(gdb) next
Breakpoint 1, print2 (string=0x7fffffffdf30 "Hello World") at 1.c:23
23 string2[size-i]=string[i];
3: string2[size-i] = 0 '\000'
2: i = 9
1: size-i = 2
(gdb) next
22 for(i=0;i<size;i++)
3: string2[size-i] = 108 'l'
2: i = 9
1: size-i = 2
(gdb) next
Breakpoint 1, print2 (string=0x7fffffffdf30 "Hello World") at 1.c:23
23 string2[size-i]=string[i];
3: string2[size-i] = 0 '\000'
2: i = 10
1: size-i = 1
(gdb) next
22 for(i=0;i<size;i++)
3: string2[size-i] = 100 'd'
2: i = 10
1: size-i = 1
(gdb) next
24 string2[size+1]='\0';
3: string2[size-i] = 0 '\000'
2: i = 11
1: size-i = 0
(gdb)
经过调试发现string2
的第一个字符就是\0
所以会出现无法法输出的情况。
用gdb可以通过查看每一次循环所赋的值找到问题所在,比我们之前不断在各个结点设置输出的方法简单的多。
gdb的基本命令:
file 装入想要调试的可执行文件
kill 终止正在调试的程序
list 列出产生执行文件的源代码的一部分
next 执行一行源代码但不进入函数内部
step 执行一行源代码而且进入函数内部
run 执行当前被调试的程序
quit (q) 退出gdb
watch 动态监视一个变量的值
make 不退出gdb而重新产生可执行文件
call name(args) 调用并执行名为name,参数为args的函数
return value 停止执行当前函数,并将value返回给调用者
break 在代码里设置断点,使程序执行到此处被挂起
gdb的调用:
gdb <可执行程序名> 一般情况下,gdb命令只使用一个参数
gdb <可执行文件名> core
如果程序运行时产生了段错误,会在当前目录下产生核心内存映像core文件,可以在指定执行文件的同时为可执行程序指定一个core文件
gdb <可执行文件名> <进程号>
为要执行的文件指定一个进程号
eg: gdb text 3000
首先,gdb会寻找一个文件名为3000的文件,如果找不到,则把调试程序text的进程号(PID)设成3000