嵌入式之gdb调试篇

一、gdb简介
GDB是一个由GNU开源组织发布的、UNIX/LINUX操作系统下的、基于命令行的、功能强大的程序调试工具。 对于一名Linux下工作的c/c++程序员,gdb是必不可少的工具。

二、gdb基本命令使用

查看断点
info break [n] – n断点号 简写:i b

设置断点
break filename:linenum 在源文件filename的linenum行处停住。
break 在进入指定函数时停住
break … if …可以是上述的参数,condition表示条件,在条件成立时停住。比如在文件thread.c中,可以设置break if sum == 4,表示当sum为4时停住程序。
例如:

gdb)b thread.c:64 if sum == 4

删除禁用断点
delete 删除所有断点 简写:d
delete breakpoint [n] 删除某个断点
disable breakpoint [n] 禁用某个断点
enable breakpoint [n] 使能某个断点

恢复程序运行和单步调试
continue 继续运行程序直到下一个断点 简写:c
next 逐过程步进,不会进入子函数 简写:n
setp 逐语句步进,会进入子函数 简写:s
until 运行至当前语句块结束 简写:u
finish 运行至函数结束并跳出,并打印函数的返回值

变量的调试

打印变量值的格式:
print(可简写为p)打印变量内容
p temp;默认十进制打印
p /x temp;按十六进制打印
x 按十六进制格式显示变量。
d 按十进制格式显示变量。
u 按十六进制格式显示无符号整型。
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a 按十六进制格式显示变量。
c 按字符格式显示变量。
f 按浮点数格式显示变量。

打印基本类型,结构体、数组等
(1)打印基本类型,结构体、数组等,则 直接p 变量,即可把对应变量的值(包括其成员)全部打印出来
(2)如果变量是指针变量,要打印内容,需要p *变量,如果海思p 变量,则只会打印对应的地址。
(3)除了可以打印全部内容,也可以打印成员变量,包括结构体的成员,数组元素等。只需p 变量成员。

设置变量
set var 变量=xxx

打印全局变量与局部变量
如果你的局部变量和全局变量发生冲突(重名),一般情况下是局部变量会隐藏全局变量,如果一个全局变量和一个函数中的局部变量同名时,如果当前停止点在函数中,用print显示出的变量的值会是函数中的局部变量的值。如果此时你想查看全局变量的值时,你可以使用“::”操作符:
file::variable
function::variable
可以通过这种形式指定你所想查看的变量,是哪个文件中的或是哪个函数中的。例如,查看文件thread.c中的全局变量x的值:
gdb) p ‘thread.c’::sum --文件要加上单引号 查看文件的全局变量sum
gdb) p sdd::sum --查看函数sdd的局部变量sum

观察点(WatchPoint)
在变量读、写或变化时中断,这类方式常用来定位bug。
watch 变量 变量发生变化时中断
rwatch 变量 变量被读时中断
awatch 变量 变量值被读或被写时中断

使用步骤如下

  1. 使用break在要观察的变量所在处设置断电;
  2. 使用run执行,直到断点;
  3. 使用watch设置观察点;
  4. 使用continue观察设置的观察点是否有变化。

调试方式运行程序
(1)调试启动无参程序
gdb 可执行文件

gdb thread

(2)调试启动带参程序
gdb 可执行文件
set args 参数
run运行

gdb thread
gdb)set args a b c
gdb)r

注:show args 命令可以查看设置好的运行参数。

(3)在线调试程序
gdb attach 进程ID

注:如果程序已经在运行,需要使用gdb attach 进程ID,在线调试,不会再开进程。如果程序还没运行,使用gdb 可执行文件,则会启动进程。

三、gdb应用例子
(1)线程卡死问题
在Linux上,执行有多线程的程序时,可能因为各种原因而导致卡死,比如死锁现象,很难快速定位问题,借助gdb attach在线调试即可排查程序卡死问题(死锁问题)。
多线程调试命令:

  1. bt:查看函数调用栈的所有信息,当程序执行异常时,可通过此命令查看程序的调用过程;
  2. info threads:显示当前进程中的线程;
  3. thread id:切换到具体的线程id,一般切换到具体的线程后再执行bt等操作。

排查步骤:
1、info threads 查看有哪些线程
2、thread id 切换到可疑线程
3、 bt 查看函数调用栈的所有信息,即可定位死锁问题。

gdb测试例程:

#include <pthread.h>
#include<stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/prctl.h>
int sum = 9;
typedef struct student
{
	char name[24];
	int age;
	int six;
}stu;
pthread_mutex_t info_mutex;
void *myroutinue(void *arg)
{
	//stu student;
	//student = *(stu *)arg;
	stu *student = arg;
	int a;
	printf("pthread_self( ) = %x\n",pthread_self( ));
	prctl(PR_SET_NAME,"Thread_snmp",0,0,0);
	pthread_detach(pthread_self( ));
	while(1)
	{
		int mun=0;
		pthread_mutex_lock(&info_mutex);
		mun++;
		//pthread_mutex_unlock(&info_mutex);
		printf("student.name = %s\n",student->name);
		printf("student.age = %d\n",student->age);
		printf("student.six = %d\n",student->six);
		printf("mun1 = %d\n",mun);
		
		sleep(2);	
	}
}

int sdd()
{
	int a=4;
	a+=5;
	int sum =8;
	return a;
}

int main(char argc,char **argv)
{
	
	int mun=0,i,n;
	for(n=0;n<argc;n++)
	{
		printf("argv[%d] = %s\n",n,argv[n]);
	}
	int sum = 0;
	pthread_t tid;
	stu *student;
	int va = 6;
	int stud[12] = {8,8,3,4,5,6,7,3};
	stu stu1;
	stu1.age = 17;
	stu1.six = 165;
	pthread_mutex_init(&info_mutex, NULL);
	void *p = (void*)malloc(sizeof(stu));
	student = (stu *)p;
	strcpy(student->name,"chenjiaguang");
	student->age = 16;
	student->six = 43;
	pthread_create(&tid , NULL , myroutinue , p);
	printf("tid = %x",tid);
	pthread_mutex_lock(&info_mutex);
	mun++;
	pthread_mutex_unlock(&info_mutex);
	sdd();
	for(i=0;i<10;i++)
	{
		sum++;
	}
	while(1)
	{
		mun++;
		printf("mun = %d\n",mun);
		sleep(2);
	}
	return 0;
}

测试效果:
运行gdb attach ip

(gdb) info threads
  Id   Target Id         Frame 
* 1    Thread 0x7f7231ac4700 (LWP 104014) "thread" 0x00007f72313a030d in nanosleep () at ../sysdeps/unix/syscall-template.S:84
  2    Thread 0x7f72312d3700 (LWP 104015) "Thread_snmp" __lll_lock_wait () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135
(gdb) thread  2
[Switching to thread 2 (Thread 0x7f72312d3700 (LWP 104015))]
#0  __lll_lock_wait () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135
135     ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: 没有那个文件或目录.
(gdb) bt
#0  __lll_lock_wait () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135
#1  0x00007f72316a7dbd in __GI___pthread_mutex_lock (mutex=0x6020c0 <info_mutex>) at ../nptl/pthread_mutex_lock.c:80
#2  0x0000000000400923 in myroutinue (arg=0x12e1420) at thread.c:27
#3  0x00007f72316a56ba in start_thread (arg=0x7f72312d3700) at pthread_create.c:333
#4  0x00007f72313db41d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109

从上面可以看出,是在pthread_mutex_lock死锁,只有锁,没有解锁,从而导致死锁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值