调试工具之GDB的基本使用

GDB基本使用

GDB是Linux下一款非常强大的调试软件,其实就是GNU Debugger的缩写。接下来我们学习一下他的基本使用。
例子函数,其中只有一个ds18b20的采集温度函数和一个主函数:

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>

int measure_temp(float *temp);

int main(int argc,char *argv[])
{
	float 				   temp = 0;

	measure_temp(&temp);

	printf("the temp:%f\n",temp);

	return 0;
}

int measure_temp(float *temp)
{
	int					   fd = -1;//打开ds18b20时候的文件描述符
	int					   found = -1;//是否找到chip的参数。
	char            	   *w1_path = "/sys/bus/w1/devices/"; //文件名的前半段,28-后面不能确定,因为设备号会变化,我们一会获取。
	char				   chip[32];//文件名的后半段,-28
	char				   ds_path[128];//拼凑出全部的路径名
    DIR					   *dirp = NULL;//打开w1时返回的DIR类型文件指针
    struct dirent          *direntp = NULL;//是readdir后返回的文件夹信息结构体指针
    char				   buf[1024];
    char 				   *ptr;//用来指向温度值

	if (NULL == temp)
	{
		printf("mesure_temp arguments error:[%s]\n",strerror(errno));
		return -1;
	}
	printf("measure_temp arguments right!\n");
    
	//打开devices文件夹
	if ( NULL == (dirp = opendir(w1_path)) )
	{
		printf("open w1_path error:[%s]\n",strerror(errno));
		return -2;
	}
	printf("open w1_path DIR[%p] success!\n",dirp);

	//readdir查找这个文件夹下有什么
	while(NULL != (direntp=readdir(dirp)))
	{
		if (strstr(direntp->d_name,"28-"))
		{
			strncpy(chip,direntp->d_name,sizeof(chip));//duancuowu
			found = 1;
		}
	}
	closedir(dirp);

	if (found < 0)
	{
		printf("nofind \"-28\" \n");
		return -3;
	}
	printf("find chip success[%s]\n",chip);
    
	snprintf(ds_path,sizeof(ds_path),"%s%s/w1_slave",w1_path,chip);
    printf("ds_path:%s\n",ds_path);

	if ((fd = open(ds_path,O_RDONLY)) < 0)
	{
		printf("open error[%s]\n",strerror(errno));
		return -4;
	}

	int i;
	int *p = NULL;
	p = &i;
	//read fd 
	memset(buf,0,sizeof(buf));
	if ( read(fd,buf,sizeof(buf)) <=0 )
	{
		printf("error:[%s]\n",strerror(errno));
		return -5;
	}
	//printf("temperature:[%s]\n",buf);

	if ( NULL == (ptr = strstr(buf,"t=") ))
	{
		printf("nofound error[%s]\n",strerror(errno));
		return -6;
	}

	//printf("%s\n",ptr);
	ptr += 2;

	*temp = atof(ptr)/1000;

	return 0;
}


(1)首先我们使用 gcc 直接生成的程序是没有调试信息的,所以我们要使用 gcc -g 命令来生成一个带有调试信息版本的目标文件。

在这里插入图片描述

(2)然后我们用 gdb 来打开这个目标文件,其实就是让带有调试信息的二进制文件在我们 gdb 的这个 “盒子” 里面进行运行。 用 gdb + 目标文件 命令来运行它。

在这里插入图片描述

(3)之后我们就可以开始调试啦!如何让 test_gdb.o 这个文件在gdb中跑起来呢?在 gdb 中输入 run 就可以了。

在这里插入图片描述

(4)不过我们发现,这和不使用 gdb 跑程序没有什么区别,所以我们学习如何增加断点。

增加断点是通过 break 命令来实现的,他有三种基本的使用形式,如下:

(gdb) break main               	# 在 main 函数处设置断点
(gdb) break my_program.c:10    	# 在 my_program.c 文件的第 10 行设置断点
(gdb) break my_function        	# 在 my_function 函数处设置断点

(5)这里假设我们程序异常退出了,但我们不清楚导致退出的错误是发生在 measure 测温函数内还是函数之前,我们就可以在进入这个函数之前,设置一个断点,然后运行它。
在这里插入图片描述我们可以看到,程序成功运行到了这个函数前,没有抛出异常,那么我们就可以确定,异常是在 measure 测温函数内的了。

(6)使用 next 单步执行,但是不进入到函数内部。

在这里插入图片描述

(7)也可以使用step单步执行,但是会进入到函数内部。

在这里插入图片描述

(8)使用bt命令或者backtrace命令显示调用的栈信息:

在这里插入图片描述

(9)显示所有的断点:

在这里插入图片描述

(10)删除特定的某一个断点:

在这里插入图片描述

运行到某一个断点后,要直接运行到下一个断点,使用continue 或者 c 就可以了。若后面没有断点了,那么就会一直运行到结束或者某个循环里面。

命令汇总:

(gdb) break main               	# 在 main 函数处设置断点
(gdb) break my_program.c:10    	# 在 my_program.c 文件的第 10 行设置断点
(gdb) break my_function        	# 在 my_function 函数处设置断点

(gdb) next                     # 或 (gdb) n 单步执行,不进入函数内部
(gdb) step                     # 或 (gdb) s 单步执行,进入函数内部
(gdb) finish                   # 运行到当前函数返回的位置
(gdb) until                    # 运行到循环结束的位置

(gdb) run                      # 启动程序
(gdb) continue                 # 或 (gdb) c 继续运行直到下一个断点

(gdb) backtrace                # 或 (gdb) bt 显示调用栈
(gdb) frame n                  # 切换到调用栈中的第 n 帧
(gdb) info frame               # 显示当前帧的信息
(gdb) info locals              # 显示当前帧的局部变量

(gdb) info breakpoints         # 或 (gdb) info b 显示所有断点
(gdb) delete breakpoint_number # 或 (gdb) d breakpoint_number 删除特定断点
(gdb) clear                    # 删除当前行的断点
(gdb) disable breakpoint_number# 禁用特定断点
(gdb) enable breakpoint_number # 启用特定断点

当然,我们也可以在运行过程中对某些变量进行查看和修改:
在这里插入图片描述

这里用到的命令是:

print 变量名  			#打印变量的值,注意,没有print,没有f。
set var 变量 =# 改变某个变量的值
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值