自学Linux 7—用 GDB 调试程序

39 篇文章 2 订阅
1 篇文章 0 订阅

用 GDB 调试程序

  要使程序能够正常运行,跟踪代码、 调试漏洞是不可缺少的。Linux 中包含一个很强大的调试工具 GDB (GNU Debuger),可以用它来调试 CC++ 程序。GDB 提供了以下功能:

  █ 在程序中设置断点,当程序运行到断点处暂停。
  █ 显示变量的值,可以打印或者监视某个变量,将变量的值显示出来。
  █ 单步执行,GDB 允许用户单步执行程序,可以跟踪进入函数和从函数中退出。
  █ 运行时修改变量的值,GDB 允许在调试状态下修改变量的值,此功能在测试程序的时候是十分有用的。
  █ 路径跟踪,GDB 可以将代码的路径打印出来,方便用户跟踪代码。
  █ 线程切换,在调试多线程的时候,此种功能是必须的。

  GDB 的功能远不止这些,例如可以显示程序的汇编代码、打印内存的值等。

一、编译可调试程序

  GDB 是一套字符界面的程序集,可以使用命令 gdb 加载要调试的程序。例如输入 gdb 后显示 GDB 的版权声明(本实例以 Ubuntu 为例)

$ gdb
GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2.1) 7.4-2012.04 
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/ gpl.htral>
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://bugs.launchpad.net/gdb-linaro/>.
(gdb)

  在此状态下输入 q,退出 GDB,要使用 GDB 进行调试,在编译程序的时候需要加入 -g 选项。例如编译如下代码。

/* 文件名:gdb_01.c */
#include<stdio.h>	/* 用于 printf */
#include<stdlib.h>	/* 用于 malloc */
/* 声明函数 sum() 为 static int 类型 */ 
static int sum(int value);
/* 用于控制输入输出的结构 */ 
struct inout
{ 
	int value; 
	int result;
}int main(int argc, char *argv[])
{
	struct inout *io = (struct inout*)malloc(sizeof(struct inout)); /* 申请内存 */
	if(NULL == io)  			/* 判断是否成功 */
	{
		printf("申请内存失败\n");/* 打印失败信息 */
		return -1; 				/* 返回 -1 */
	}
	if(argc !=2)	/* 判断输入参数是否正确 */
	{
		printf("参数输入错误!\n"); 	/* 打印失败信息 */
		return -1; 					/* 返回-1 */
	}
	io->value =*argv[1]-'0'; 		/* 获得输入的参数 */
	io->result = sum(io->value); 	/* 对 value 进行累加求和 */ 
	printf("你输入的值为:%d,计算结果为:%d\n",io->value,io->result);
	return 0;
}
/* 累加求和函数 */
static int sum(int value)
{
	int result = 0; 
	int i = 0;
	for (i=0; i<value; i++)	/* 循环计算累加值 */
	{
		result += i;
	}
	return result; /*返回结果*/
}

  上面的代码实现了一个累加求和,例如对 sum 输入 3,其结果应该是 6=1+2+3。编译代码如下:

$gcc -o test gdb_01.c -g 

  生成了 test 的可执行文件。运行此程序:

$./test 3
你输入的值为:3,计算结果为:3

  GDB 之所以能够调试程序在于进行编译时的 -g 选项,当设置了这个选项的时候,GCC 会向程序中加入“楔子”,GDB 能够利用这些楔子与程序交互。

二、使用 GDB 调试程序

  前面提到,将源文件 gdb_01.c 编译成目标文件 test。在编译的时候加入了 -g 选项, 可以使用 GDB 对可执行文件 test 进行调试。下面利用 GDB 调试 test,査找 test 计算错误的原因。

1. 加载程序

  使用 GDB 加载程序的时候,需要先将程序加载到 GDB 中。加载程序的命令格式为“ gdb 要调试的文件名 ”例如,下面的命令将可执行文件 test 加载到 GDB 中。

$gdb test		 (gdb 命令+调试的可执行文件)
GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2.1) 7.4-2012.04 
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://bugs.launchpad.net/gdb-linaro/>...
Reading symbols from /home/linux-c/Linux_net/02/2.4.1/test...done.
(gdb)  		(等待输入调试命令)
2. 设置输入参数

  通常可执行文件在运行的时候需要输入参数,GDB 中向可执行文件输入参数的命令格式为“ set args 参数值1 参数值2 …”。例如,下面的命令 set args 3 表示向可执行文件输入的参数设为 3,即传给 test 程序的值为 3

(gdb) set args 3		(设置参数 args 为 3)
(gdb)
3. 打印代码内容

  命令 list 用于列出可执行文件对应源文件的代码,命令格式为“ list 开始的行号 ”。例如,下面的命令 list 1,从第一行开始列出代码,每次按 Enter 键后顺序向下列出代码。

(gdb) list 1
/* 文件名:gdb-01.c */
#include <stdio.h>	/* 用于 printf */
#include <stdlib.h> /* 用于 malloc */
/* 声明函数 sum() 为 static int 类型 */ 
static int sum(int value);
/* 用于控制输入输出的结构 */ 
struct inout
{ 
	int value; 
	int result;
};
(gdb)	(按下 Enter 键)
int main(int argc, char *argv[])
{
	struct inout *io = (struct inout*)malloc(sizeof(struct inout)); /* 申请内存 */
	if(NULL == io)		/* 判断是否成功 */
	{
		printf("申请内存失败\n"); /* 打印失败信息 */
		return -1;				/* 返回-1 */
	}
(gdb)	(按下 Enter 键) 
	if(argc != 2)		/* 判断输入参数是否正确 */
	{
		printf(”参数输入错误!\n"); /*打印失败信息*/
		return -1;	/* 返回-1 */
	}
	io->value =*argv[1]-'0';	/* 获得输入的参数 */
	io->result = sum(io->value);	/* 对 value 进行累加求和 */
	printf("你输入的值为:%d,计算结果为:*d\n",io->value,io->result);
	return 0;
(gdb)	(按下 Enter 键}
}
/*累加求和函数*/ 
static int sum(int value)
{ 
	int result = 0; 
	int i = 0;
	for(i=0;i<value;i++)	/* 循环计算累加值 */
	{
		result += i;
	}
	return result;			/* 返回结果 */
(gdb)	(按下 Enter 键)
}
(gdb)	(按下 Enter 键}
Line number 42 out of range; gdb-1.c has 41 lines.
(gdb)
4. 设置断点

  b 命令在某一行设置断点,程序运行到断点的位置会中断,等待用户的下一步操作指令。

(gdb) b 38
Breakpoint 1 at 0x8048502: file gdb-1.c, line 38.
(gdb)
5. 运行程序

  GDB 在默认情况下是不会让可执行文件运行的,此时,程序并没有真正运行起来,只是装载进了 GDB 中。要使程序运行需要输入 run 命令。

(gdb) run 3
Starting program: /home/linux-c/Linux_net/02/2.4.1/test 3
Breakpoint 1, sum (value=3) at gdb-1.c:38 
38		result += i;	(此处遇到断点)
(gdb)
6. 显示变量

  在程序运行到第 4 步所设置的 38 行断点的时候,程序会中断运行等待进一步的指令。这时可以进行一系列的操作,其中,命令 display 可以显示变量的值。

(gdb) display i (每次停止时显示变量i的值)
1: i = 0
(gdb) display result (每次停止时显示变量result的值) 
2: result = 0
1:i = 1
(gdb) c (继续运行)
Continuing.

Breakpoint 1, sum (value=3) at	gdb-1.c:38
38		result += i;
2: result = 1
1:i = 2
(gdb)	(继续运行)
Continuing.

你输入的值为:3,计算结果为:3
[Inferior 1 (process 9520) exited normally] 
(gdb)

  通过上面的跟踪,已经可以判断出问题出在 for(i=0;i<value;i++); 此行代码上,可以将其修改为 for(i=1;i<=value;i++),或者修改 result+=iresult+=(i+1)

7. 修改变量的值

  要在 GDB 中修改变量的值,使用 set 命令。

(gdb) set result=6			(修改 result 值为 6)
(gdb) c						(继续运行)
Continuing.
你输入的值为:3,计算结果为:12
[Inferior 1 (process 9563) exited normally]
8. 退出 GDB

  在调试完程序后,使用 q 命令退出 GDB

(gdb) q						(退出)
$
三、GDB 常用命令

  前面举了一个简单的例子来演示 GDB 的使用,接下来详细介绍 GDB 的常用命令。参见下表(GDB 常用命令表)主要包含信息获取、断点设置、运行控制、程序加载等常用命令,这些函数可以进行调试时的程序控制、程序的参数设置等。

GDB 的命令格 式含义简写
listlist [开始, 结束]列出文件的代码清单l
printprint p打印变量内容p
breakbreak [行号|函数名称]设置断点b
continuecontinue [开始, 结束]继续运行c
infoinfo para列出信息i
nextnext下一行n
stepstep进入函数S
displaydisplay para显示参数
filefile path加载文件
runrun args运行程序r
1. 执行程序

  用 GDB 执行程序可以使用 gdb program 的方式,program 是程序的程序名。当然,此程序编译的时候要使用 -g 选项。假如在启动 GDB 的时候没有选择程序名称,可以在 GDB 启动后使用 file program 的方法启动。例如:

(gdb)file test

  如果要运行准备好的程序,可以使用 run 命令,在它后面是传递给程序的参数,例如:

(gdb) run 3
你输入的值为:3 ,计算结果为:6
[Inferior 1 (process 9577) exited normally]

  如果使用不带参数的 run 命令,GDB 就再次使用前一条 run 命令的参数。

2. 参数设置和显示

  使用 set args 命令来设置发送给程序的参数:使用 show args 命令就可以査看其默认的参数。

(gdb)set args 3 
(gdb)show args
Argument list to give program being debugged when it is started is "3". 
(gdb)	(按下 Enter 键)
Argument list to give program being debugged when it is started is "3".

  如果按 Enter 键,GDB 默认执行上一个命令。例如上面的例子中在执行命令 show args 后,按 Enter 键会接着执行 show args 命令。

3. 列文件清单

  打印文件代码的命令是 list,简写为 llist 的命令格式为:

list line1,line2

  打印出从 line1line2 之间的代码。如果不输入参数,则从当前行开始打印。例如,打印出从第 2 行到第 5 行之间的代码:

(gdb) l 2,5
#include <stdio.h>	/* 用于 printf	*/
#include <stdlib.h>	/*用于 malloc	*/
/*	声明函数 sum() 为 static int 类型 */
static int sum(int value);
(gdb)
4. 打印数据

  打印变量或者表达式的值可以使用 print 命令,简写为 p。它是一个功能很强的命令,可以打印任何有效表达式的值。除了可以打印程序中的变量值之外,还可以打印其他合法的表达式。print 的使用方式为:

(gdb) print 	var	(var 为参数)

  █ print 命令可以打印常量表达式的值,例如,打印 2+3 的结果:

(gdb) p 2+3 
$7= 5

  █ print 命令可以计算函数调用的返回值,例如,打印调用函数 sum()3 求和:

(gdb) p sum(3)
$8 = 6

  █ 打印一个结构中各个成员的值,例如打印上面代码中的 io 结构中各个成员的值:

(gdb) p *io
$9 = {value = 3, result = 6}

  █ GDB 的系统中,之前打印的历史值保存在全局变量中。如 $9 中保存了结构 io 的值,用 print 可以打印历史值,例如:

(gdb) p $9
$3 = {value = 3, result = 6}

  █ 利用 print 命令可以打印构造数组的值,给出数组的指针头并且设定要打印的结构数量,print 命令会依次打印各值。打印构造数组的格式为:

基地址@个数

  例如,*io 是结构 ioout 的头,要打印从 io 开始的两个数据结构(当然最后一个是非法的,这里只是举一个例子)。

(gdb) p *io@2
$13 = {{value = 3, result * 6}{value = 0, result = 135153}}
5. 断点

  设置断点的命令是 break,简写为 b。有如下 3 种形式,注意 GDB 的停止位置都是在执行程序之前。

  █ break 行号:程序停止在设定的行之前;
  █ break 函数名称:程序停止在设定的函数之前;
  █ break 行号或者函数 if 条件:这是一个条件断点设置命令,如果条件为真,则程序在到达指定行或函数时停止。

  (1)设置断点。如果程序由很多的文件构成,在设置断点时要指定文件名。例如:

(gdb) b gdb-01.c:38	(在文件gdb-01 .c的第 38 行设置断点}
Note: breakpoint 4 also set at pc 0x804849c.
Breakpoint 5 at 0x804849c: file gdb-01.c, line 38.
(gdb) b gdb-01.c:sum	(在文件 gdb-01 .c 的函数 sum 处设 IS 断点)
Breakpoint 6 at 0x8048485: file gdb-01.c, line 28.

  要设置一个条件断点,可以利用 break if 命令,在调试循环代码段时这样的设置比较有用,省略了大段的手动调试。例如,在 sum() 函数中,当 i2 时要设置断点,如下所示。

(gdb) b 38 if i==2
Breakpoint 8 at 0x804849c: file gdb-01.c, line 38.
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /horae/linux-c/Linux_net/02/2.4.1/test 3
Breakpoint 3, sum (value=*3) at gdb-01.c:38 
38	result += i;

  (2)显示当前 GDB 的断点信息。使用 info break 命令显示当前断点的信息,例如,列出当前的断点信息:

(gdb) info break
Num Type	Disp Enb Address What
2	breakpoint	keep y 0x080484bc in main at gdb-01.c:29
3	breakpoint	keep y 0x08048502 in sum at gdb-01.c:38
	stop only if i=2
	breakpoint already hit 1 time

  信息分为 6 类:Num 是断点的编号,Type 是信息的类型,Disp 是描述,Enb 是断点是否有效,Address 是断点在内存中的地址,What 是对断点在源文件中位置的描述。

  第 3 个断点的停止条件为当 i==2 时,已经命中了 1 次。

  (3)删除指定的某个断点。删除某个指定的断点使用命令 delete,命令格式为“ delete breakpoint 断点编号 ”。例如,下面的命令 delete b 3 会删除第 3 个断点。

(gdb) delete breakpoints 3 
(gdb) info b
Num Type	Disp Enb Address What
2	breakpoint keep y 0x080484bc in main at gdb-01.c:29

  上面的命令会删除断点的编号为 3 的断点。如果不带编号参数,将删除所有的断点。

  (4)禁止断点。禁止某个断点使用命令 disable,将某个断点禁止后,GDB 进行调试的时候,在断点处程序不再中断。命令的格式为 “disable breakpoint 断点编号”。例如,下面的命令 disable breakpoint 2,将禁止使用断点 2,即程序运行到断点 2 的时候此程序不会停止,同时断点信息的使能域将变为 n

(gdb) disable b 2

  (5)允许断点。允许某个断点使用命令 enable,这个命令将禁止的断点重新启用,GDB 会在启用的断点处重新中断。命令的格式为 “enable breakpoint 断点编号”。例如,下面的命令 enable breakpoint 2,将允许使用断点 2,即程序运行到断点 2 的时候此程序会停止,同时断点信息的使能域将变为 y

(gdb) enable b 2

  (6)清除断点。一次性地清除某行处的所有断点使用命令 clear,这个命令将清除某行的所有断点信息。将某行的断点清除后,GDB 将不再保存这些信息,此时不能使用 enable 命令重新允许断点生效。如果想重新在某行处设置断点,则必须重新使用命令 breakpoint 进行设置。命令的格式为 “clear 源代码行号” 例如,下面的命令 clear 29,将清除在源代码文件中第 29 行所设置的断点。

(gdb)clear 29
6. 变量类型检测

  在调试过程中有需要查看变量类型的情况,此类命令有 whatisptype 等。

  █ 打印数组或者变量的类型 whatis:要查看程序中某个变量的类型,可以使用命令 wahtiswhatis 命令的格式为 “whatis 变量名”,其中的变量名是要查看的变量。 例如查看 ioargc 的变景类型,iostruct inout 类型,argcint 类型。

(gdb) whatis *io 
type = struct inout 
(gdb) whatis argc 
type = int

  █ 结构的详细定义 ptype:使用 whatis 命令査看变量的类型时,只能获得变量的类型名称,不能得到类型的详细信息。如果想要査看变量的详细信息,需要使用命令 ptype,例如查看 io 的类型,最后的 * 表明 io 是一个指向 struct inout 类型的指针。

(gdb) ptype io 
type = struct inout 
{ 
	int value; 
	int result;
}
7. 单步调试

  在调试程序的时候经常遇到要单步跟踪的情况,并在适当的时候进入函数体的内部继续跟踪。GDBnext 命令和 step 命令提供了这种功能。next 命令是单步跟踪的命令,简写为 nstep 是可以进入函数体的命令,简写为 s。如果已经进入某个函数,想退出函数的运行,返回到调用的函数中,要使用命令 finish。例如在代码的第 28 行设置断点,跟踪程序,在第 34 行进入 sum() 函数的内部继续跟踪。

(gdb) b 28	(在 28 行处设罝断点)
Breakpoint 5 at 0x80484a7: file gdb-Ol.c, line 28.
(gdb) run 3	(运行程序,输入参数为 3)
Starting program: /home/linux-c/Linux_net/02/2.4.1/test 3
(在 28 行断点处停下)
Breakpoint 5, main (argc=2, argv=Oxbffff244) at gdb-01.c:28
28	io->result=sum(io->value);	/* 对 value 进行累加求和 */ 
(gdb) s		(进入函数体sum内部)
sum (value=3) at gdb-01.c:34
34	int result = 0;
(gdb) n 	(单步执行)
35	int i = 0;
(gdb) n		(单步执行)
37	for(i=0;i<=value;i++)	/* 循环计算累加值 */
{
	(gdb) finish		 (执行完函数 sum)
}
Run till exit from #0 sum (value=3) at gdb-O1.c:37 
0x080484b5 in main (argc=2, argv=0xbffff244) at gdb-01.c:28
28	io->result = sum(io->value);		/* 对 value 进行累加求和 */
Value returned is $9 = 6 			 (函数 sum 执行完毕,结果为 6)
(gdb) n								(单步执行)
29	printf("你输入的值为:%d,计算结果为:%d\n",io->value, io->result); 
(gdb) c			(继续执行到程序结束或者下一个断点)
Continuing.
你输入的值为:3,计算结果为:6
[Inferior 1 (process 9772) exited normally]
(gdb)
8. 设置监测点

  命令 display 可以显示某个变量的值,在结束或者遇到断点的时候,将设置变量的值显示出来。当然是否显示还要看变量的作用域,display 只显示作用域内变量的值。例如,将 iosum 中的 result 设置为显示,设置断点在第 27 行、第 29 行和第 38 行,进行调试的情况如下:

$ gdb test	(运行GDB,加载程序test)
linux-c@linuxc-virtual-machine:~/Linux_net/02/2.4.1$ gdb test 
GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2.1) 7.4-2012.04 
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://bugs.launchpad.net/gdb-linaro/>...
Reading symbols from /home/linux-c/Linux_net/02/2.4.1/test...done.
(gdb) b 27	 	(在第 27 行设罝断点)
Breakpoint 1 at 0x8048490: file gdb-Ol.c, line 27.
(gdb) b 29		(在第 29 行设罝断点)
Breakpoint 2 at 0x80484bc: file gdb-Ol.c, line 29.
(gdb) b 38		(在第 38 行设置断点)
Breakpoint 3 at 0x8048502: file gdb-Ol.c, line 38.
(gdb) run 3		(运行程序 test,输入参数 3,将在第 27 行断点处停下)
Starting program: /home/linux-c/Linux一net/02/2.4.1/test 3

Breakpoint 1, main (argc=2, argv=0xbffff244) at gdb-01.c:27 
27	io->value = *argv[l]-'0';	/* 获得输入的参数 */
(gdb) display *io	(设置显示参数 *io)
1: *io = {value = 0, result = 0}	(显示当前值)
(gdb) c	(继续运行,将在第 46 行断点处停下)
Continuing.

Breakpoint 3, sum (value=3) at gdb-01.c:38
38	result += i;		(在第 38 行断点处停下)
(gdb) display result 	(设置显示参数 result)
2: result = 0 
(gdb) n					(单步执行,到下一行停下,并显示 result 的值)
37	for(i=0;i<=value;i++)  /*循环计算累加值*/
2: result = 0 			(当前值为 0)
(gdb) c 				(继续执行,到第 38 行断点处停下)
Continuing.

Breakpoint 3, sum (value=3) at gdb-01.c:38
38	result += i;
2: result = 0			(result 当前值为 0)
(gdb) c 				(继续执行,到第 38 行断点处停下)
Continuing.

Breakpoint 3, sum (value=3) at gdb-01.c:38
38	result += i;
2: result = 3	(result 当前值为 3)
(gdb) c			(继续执行,到第 29 行断点处停下)
Continuing.

Breakpoint 2, main (argc=2, argv=Oxbffff244) at gdb-01.c:29 
29 printf("你输入的值为:%d,计算结果为:%d\n",io->value,io->result); 
1: *io = {value = 3, result = 6}	(在此处 *io 在其作用域,显示 *io 的当前值) 
(gdb) c	(继续执行)
Continuing.
你输入的值为:3,计算结果为:6
[Inferior 1 (process 9810) exited normally]
(gdb)
9. 调用路径

  backtrace 命令可以打印函数的调用路径,提供向前跟踪功能,此命令对跟踪函数很有用处。backtrace 命令打印一个顺序列表,函数从最近到最远的调用过程,包含调用函数和其中的参数。其简写为 bt。例如在第 38 行设置断点后打印调用过程:

(gdb) bt
#0 sum (value=3) at gdb-01.c:38
#1 0x080484b5 in main (argc=2, argv=0xbffff244) at gdb-01.c:28
10. 信息 info

  info 命令可以获得当前命令的信息,例如获得断点的情况,参数的设置情况等。

11. 多线程 thread

  多线程是现代程序中经常采用的编程方法,而多线程由于执行过程中的调度随机性, 不好调试。多线程调试主要有两点:先获得线程的 ID 号,然后转到该线程进行调试。
  info thread 命令列出当前进程中的线程号,其中最前面的为调试用的 ID
thread id 进入需要调试的线程。

12. 汇编 disassemble

  disassamble 命令打印指定函数的汇编代码,例如 sum 的汇编代码如下:

(gdb) disassemble sum
Dump of assembler code for function sum:
0x080484e5 <+0>: push %ebp 
0x080484e6 <+l>: mov %esp,%ebp 
0x080484e8 <+3>: sub $0x10,%esp 
0x080484eb <+6>: movl $0x0,-0x8(%ebp)
0x080484f2	<+13>:	movl	$0x0,-0x4(%ebp)
0x080484f9	<+20>:	movl	$0x0,-0x4(%ebp)
0x08048500	<+27>:	jmp		0x804850c <sum+39>
=> 0x08048502	<+29>:		mov	-0x4(%ebp),%eax
0x08048505	<+32>:	add		%eax,-0x8(%ebp)
0x08048508	<+35>:	addl	$0x1,-0x4(%ebp)
0x0804850c	<+39>:	mov		-0x4(%ebp),%eax
0x0804850f	<+42>:	cmp		0x8(%ebp),%eax
0x08048512	<+45>:	jle		0x8048502 <sum+29>
0x08048514	<+47>:	mov		-0x8(%ebp),%eax
0x08048517  <+50>: 	leave
0x08048518  <+51>: 	ret
End of assembler dump.
13. GDB 的帮助信息

  在使用本例时,小伙伴可能会遇到一些困扰,例如命令 c 是什么意思,display 是什么等。 这些在 GDB 中可以利用 help 命令来获得帮助。例如:

(gdb) help
List of classes of commands: 

aliases -- Aliases of other commands
breakpoints -- Making program stop at certain points 
data -- Examining data
files ——Specifying and examining files
internals -- Maintenance commands
obscure -- Obscure features
running -- Running the program
stack -- Examining the stack
status -- Status inquiries
support -- Support facilities
tracepoints -- Tracing of program execution without stopping the program 
user-defined -- User-defined commands

Type "help" followed by a class name for a list of commands in that class. 
Type "help all" for the list of all commands.
Type "help" followed by command name for full documentation.
Type "apropos word" to search for commands related to "word".
Command name abbreviations are allowed if unambiguous.
(gdb)

  help 命令罗列了 GDB 支持的命令,例如断点(breakpoints)、环境数据(data)等。对命令 c 等的疑问可以使用命令 help 获得解释:

(gdb) help c
Continue program being debugged, after signal or breakpoint.
If proceeding from breakpoint, a number N may be used as an argument, which means to set the ignore count of that breakpoint to N - 1 (so that the breakpoint won't break until the Nth time it is reached).

If non-stop mode is enabled, continue only the current thread, 
otherwise all the threads in the program are continued. To continue all stopped threads in non-stop mode, use the -a option. 
Specifying -a and an ignore count simultaneously is an error.

  help 解释 c 命令用于继续执行程序,并且可以设置执行的行数。其实 c 命令是 continue 的简写。

四、其他的 GDB

  除了基于命令行的 GDB 调试程序,在 Linux 下还有很多其他基于 GDB 的程序,例如 xxgdbinsight 等。

1. xxgdb

  xxgdb 对命令行的 GDB 进行了简单的包装,将 GDB 的输入、命令、输出分为了几个窗口,并且将命令用多个按钮表示,方便使用。

2. Emacs

  Emacs 集成了 GDB 的调试。可以用下面的命令启动 GDB

M-x gdb

  在 Emacs 中有种多窗口调试模式(gdb-many-windows),可以把窗口划分为 5 个窗格,同时显示 gdb 命令窗口、当前局部变量、程序文本、调用栈和断点。

  Emacsgdb 的命令和快捷键做了绑定。对于常用的命令,输入快捷键比较方便。例如,Ctrl + CCtrl + Nnext lineCtrl + CCtrl + Sstep in,在调试过程中用得最多的快捷键就是这两个。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值