1、gdb基本功能

发布时间:2023年12月30日


linux下我现在接触到的常用调试工具如下.

  • gbd
  • gdbgui
  • cmake-tools

??gdb是最为通用的,普遍linux会自带gdb工具,使用简单,无额外需求.

??gdbgui需要额外安装,且会占用处理器资源.

??cmake-tools是使用vscode远程ssh设备时在vscode上安装的一个插件,必须用cmake组织管理代码且使用vscode时才可以使用该工具借助于vscode图形化界面进行debug,但相当占用处理器资源.

下面只介绍gdb具体使用方法.

1、gdb

安装方式.

sudo apt-get install gdb

使用方法

// 无参程序调用
gdb ./<exce>
// 有参程序调用
gdb ./<exce> <param>

exce即为代码编译出来的可执行文件.

正常执行后会出现如下界面.
在这里插入图片描述

注意,这个时候程序并没有开始运行.

如果程序带有入参,则

1.1、运行

运行常用相关指令见下表.

命令简写形式说明
runr开始执行程序直到遇到 结束或者遇到断点等待下一个命令;
startst开始执行程序,在main函数中的第一条语句前停下
continuec继续程序的运行,直到遇到下一个断点
nextn执行下一条语句,如果该语句为函数调用,不会进入函数内部执行(即不会一步步地调试函数内部语句)
steps执行下一条语句,如果该语句为函数调用,则进入函数执行第一条语句
finish直接执行完当前函数,返回到调用该函数的位置
quitq推出gdb调试环境

该部分比较简单,且都比较常用,不再复述.

1.1.1、程序入参

命令简写形式说明
set args 设定运行时的参数
show args查看设定的运行参数

1.2、断点及观察点

gdb支持如下几种断点,且断点可以在程序运行前设置.

  • 普通断点,运行到该处就停止
  • 条件断点,运行到该处后且符合设定条件才停止
  • 临时断点,只生效一次的断点

观察点是运行中设置,而且只能是变量。

1.2.1、设置断点

命令简写形式说明
breakb设置断点
break ifb if条件断点,满足if后的条件后停止
tbreak临时断点,只生效一次

断点有如下几种设置方法.

// 在指定文件的指定行号设定断点
b <file_name>:<file_line>
// 在指定文件的指定函数设定断点
b <file_name>:<fun_name>
// 根据条件设定断点
b <file_name>:<file_line> if <cond>  例如:x==0

临时断点和上述用法一样.

1.2.2、禁用、删除断点

命令简写形式说明
info b显示当前所有断点
d break 删除指定断点
deleted删除所有断点
disable b 禁用指定断点
enable b 使能制定断点

想要禁用或者删除断点,需要先知道当前共有哪些断点.如下所示.

在这里插入图片描述

从左到右,分别是断点号,类型,使能状态,后面是断点具体位置.

禁用断点示例如下.对应的使能断点不在演示.

在这里插入图片描述

可以看到禁用断点2后,后面的Enb变为了n.代表断点被禁用不生效,但依旧存在.

使能断点,删除所有断点如下所示.
在这里插入图片描述

删除指定断点示例如下.

在这里插入图片描述

1.2.3、观察点

观察点是当变量变化即停止的一种调试手段.

命令简写形式说明
info b利用此方式也可以查看watch信息,也可以使用info watch在这里插入图片描述
watch 只有当被监控变量(表达式)的值发生改变,程序才会停止运行
rwatch 只要程序中出现读取目标变量(表达式)的值的操作,程序就会停止运行
awatch 只要程序中出现读取目标变量(表达式)的值或者改变值的操作,程序就会停止运行

cond可以是变量也可以是表达式.

我只用过变量.以变量说明

struct test{
    char name[16];
    uint32_t age;
};
struct test data = {0};
struct *p = &test_data;
  • watch data 当data里任意一个数据发生改变即刻停止

  • watch data.age 当data内的age发生改变时停止

  • watch *pwatch data

  • watch p 当p指向内容发生变化时即刻停止

watch设定观察点的方式有两种,默认为1.

  • 硬件观察点
  • 软件观察点

以RK3568举例,实际使用中发现最多只能建立2个硬件观察点,后续在使用watch后,会出现如下提示.

Hardware watchpoint num: Could not insert watchpoint

使用如下指令强制GDB调试器建立软件观察点.

set can-use-hw-watchpoints 0

awatch 和 rwatch 命令只能设置硬件观察点,如果系统不支持或者借助如上命令禁用,则 GDB 调试器会打印如下信息:

Expression cannot be implemented with read/access watchpoint.

备注:软件观察点会导致程序执行效率变低

1.3、打印

1.3.1、设定打印参数

命令简写形式说明
set print elements 设定打印长度
show print elements显示打印长度
set print pretty on打开换行打印

打印信息过长时,信息显示不全,可以使用set print elements进行设定显示长度.

打印结构体时,默认不换行,使用set print pretty on可以将结构体成员变量换行显示如下所示.

其中红框内的是默认打印方式,下面的是打开换行打印后的显示效果.

在这里插入图片描述

1.3.2、打印数据

命令简写形式说明
print/p打印数据
ptype <var_name>查看变量数据类型

简单介绍如下几种简单的使用方式.

int a = 1;
int *p_a = &a;
char name[32] = "name";

p a   打印变量a值
p p_a  打印p_a存储的地址,即a的地址
p *p_a  打印p_a存储地址的所存储的数据
p name  打印name中的字符串值
p name[<idx>]@<len>  打印数组name从idx索引处len长度的数据
p ++a  打印++a的值,此时程序内a的值也将发生变化
p <fun(<param>)> 将参数传入函数中,直接调用函数并打印返回值

如果想要数据按照指定的方式打印,则需要用到参数.参数常用值

fmt功能
/x十六进制的形式打印
/d有符号,十进制形式打印证书
/u无符号,十进制形式打印证书
/o八进制打印
/t二进制打印
/f浮点数打印
/c字符打印
/s字符串打印

如下所示.

p/x a             以十六进制形式打印a变量
p/s name		  以字符串形式打印name数组存储的数据
p/x name[0]@10    以十六进制形式挨个打印name数组从0到len-1索引的数据

如果当前断点在C文件,此时想查看A文件的非局部变量的值,可以通过如下方式.

p <file_name>::<var_name>

可通过下列命令打印变量的类型

ptype <var_name>

1.3.3、自动打印

上述print指令需要用户每次都输入才会执行打印功能.如果想要程序一停止就打印数据可以使用display功能.

命令简写形式说明
display
info display查看自动显示的信息,包含信息编号
disable display 失能自动输出,num代表信息编号
num可以为多个,比如disable display 2 3 4
也可以为一个范围,比如disable display 2-4
enable display 使能自动输出,num代表信息编号
num可以为多个,比如enable display 2 3 4
也可以为一个范围,比如enable display 2-4
delete display d display 删除输出, num代表信息编号,同undisplay <num>
num可以为多个,比如disable display 2 3 4
也可以为一个范围,比如disable display 2-4

display所有用法同print基本一致.

1.3.4、按照地址打印

命令简写形式说明
x/<n/f/u> 按照nfu三个参数的配置打印addr出的数据

其中,n、f、u的含义如下.

名称含义
n正整数,从addr开始,打印n个长度的数据
f打印形式,o是8进制,u是无符号10进制,t是二进制,c是字符,s是字符串等,参考print打印形式
u表示从当前地址往后请求的字节数,即一个长度的单位,默认为4字节,b表示单字节,h表示双字节,w表示四字 节,g表示八字节。

x/16xb: 打印0地址处16个长度单位的数据,每个单位长度为一个字节,共计16个字节数据以16形式打印.

文章来源:https://blog.csdn.net/a986096115/article/details/135307859
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。