登录发现更多内容
首页
分类
发帖
账号
自动登录
找回密码
密码
登录
立即注册
立即登录
立即注册
其他登录
QQ
微信
首页
Portal
求助问答
Xiuno资源
Xiuno教程
Xiuno插件
Xiuno主题
休闲茶馆
定制主题
产品教程
BBS
求助问答
Xiuno资源
Xiuno教程
Xiuno插件
Xiuno主题
休闲茶馆
定制主题
开发资料
求助问答
Xiuno资源
Xiuno教程
Xiuno插件
Xiuno主题
休闲茶馆
定制主题
样品购买
求助问答
Xiuno资源
Xiuno教程
Xiuno插件
Xiuno主题
休闲茶馆
定制主题
IoT云平台
求助问答
Xiuno资源
Xiuno教程
Xiuno插件
Xiuno主题
休闲茶馆
定制主题
GitHub
求助问答
Xiuno资源
Xiuno教程
Xiuno插件
Xiuno主题
休闲茶馆
定制主题
技术博客
求助问答
Xiuno资源
Xiuno教程
Xiuno插件
Xiuno主题
休闲茶馆
定制主题
搜索
搜索
热搜:
LoRa
ESP8266
安信可
本版
帖子
用户
请
登录
后使用快捷导航
没有账号?
立即注册
每日签到
任务
广播
导读
排行榜
设置
我的收藏
退出
9
1
0
首页
技术杂谈
›
玩转gdb调试工具(上)
返回列表
玩转gdb调试工具(上)
[ 复制链接 ]
发布帖子
可乐klelee
金牌会员
9
主题
24
回帖
1473
积分
金牌会员
金牌会员, 积分 1473, 距离下一级还需 1527 积分
金牌会员, 积分 1473, 距离下一级还需 1527 积分
积分
1473
私信
9人留言
楼主
技术杂谈
1650
9
2023-9-6 17:28:01
## 安装gdb 安装: ```bash apt install gdb ``` 查看版本: ```bash gdb --version ``` ) ## gdb的使用 我们将以下面的程序为例进行gdb的学习: ```c #include
int main () { unsigned long long int n, sum; n = 1; sum = 0; while (n <= 100) { sum = sum + n; n = n + 1; } return 0; } ``` gdb调试器是在程序运行过程中工作的,因此首先首先要将需要调试的程序编译成一个可执行程序: ```gdb gcc main.c -o main.out -Og ``` ) 不同于gcc中学到的编译生成可执行文件的过程,gdb需要的可执行文件还需要进行调试处理。所以上面的编译语句中新增了两个编译选项 `O` :大写的O,表示gcc对编译过程进行优化,去除一些比如没有用到的变量之类的代码。这个选项分为五个等级,其中`O0` 表示不优化,`O1~O4` 优化力度逐渐增强。but我们常用的是O,表示力度在0-1之间,即保证对程序做了优化,又能不影响效率。 `g` : 表示生成适合gdb的可执行文件。 ### 启动gdb调试 在上面已经生成了一个可执行文件,接下来就直接启动gdb调试: ```gdb gdb main.out ``` 直接执行上面的命令就可以进入gdb调试工具中,但是进入之前会打印一些gdb相关信息,这个可以使用`--silent` 将这些信息关掉 ) gdb工具提供了相当多的调试命令,先了解一些常用的命令: | 调试指令 | 作 用 | | -------------------------------- | -------------------------------------------------------------------------------------- | | (gdb) break xxx
(gdb) b xxx | 在源代码指定的某一行设置断点,其中 xxx 用于指定具体打断点的位置。 | | (gdb) run
(gdb) r | 执行被调试的程序,其会自动在第一个断点处暂停执行。 | | (gdb) continue
(gdb) c | 当程序在某一断点处停止运行后,使用该指令可以继续执行,直至遇到下一个断点或者程序结束。 | | (gdb) next
(gdb) n | 令程序一行代码一行代码的执行。 | | (gdb) print xxx
(gdb) p xxx | 打印指定变量的值,其中 xxx 指的就是某一变量名。 | | (gdb) list
(gdb) l | 显示源程序代码的内容,包括各行代码所在的行号。 | | (gdb) quit
(gdb) q | 终止调试。 | 想起了第一次使用vim编辑器的困惑,所以先重点说说怎么终止调试。`quit` 或者`q` ) 在gdb工具中输入quit回车,即可终止调试。 然后再正式的来看gdb调试的常见手段: #### list 或者 l 显示源代码内容,带行号 `list` list命令一次性打印10行,,类似于more命令,继续按enter键到下一行。 ) #### break 或者 b 设置断点,程序运行至断点处停止运行,只是暂停,并没有终止运行代码 ) #### run 或者 r 执行正在被调试的程序,会在第一个断点处停止 ) #### print 或者 p 打印指定变量的值 ) #### continue 或者 c 然后可以设置下一个断点,这里设置12,然后使用continue命令继续执行代码,程序会在12行的断点处停止执行 ) 接下来再次打印变量n的值,会发现经过循环,n的值已经改变了: ) 这样子,一次简单的调试就结束了,然后按执行quit退出调试:会问你是不是要退出调试,是的! ) 这就是一次简单的gdb调试,也是以后用gdb最多的命令了。 ### 调用gdb的方式 上面的例子中已经调用过一次了,它直接调用c程序的可执行文件,命令如下: ```gdb gdb main.out --silent ``` 这只是调用gdb调试的其中一种方式,常用的还有:进程调用、core文件调用,还有一种方式是直接执行gdb命令调用,当然这种方式调用因为没有可调式的文件,调用之后需要显示的指定相关的file,这个后面细说。 #### 进程调用 进程调用也就是通过一个正在执行的程序去调用gdb,需要提供相关的进程号!所以第一个问题就是,怎么获取正在执行的程序的进程号?写一个代码看看。 ```c #include
int main () { int i = 0; while (1) { i++; } return 1; } ``` ##### pid的获取 ``` pidof
``` ) 可以看到demo.out 的pid为389104 然后我们通过这个进程号来调用gdb: ``` gdb -p 389104 ``` ) 注意,当 GDB 调试器成功连接到指定进程上时,程序执行会暂停。如上所示,程序暂停至第 6 行代码 num++ 的位置,此时可以通过断点调试、逐步运行等方式监控程序的执行过程。例如: 先查看一下当前执行的代码前后逻辑,可以使用list或者l ) 然后设置个断点 `break 5` 继续执行`continue` 然后打印一下相关变量的值`print i` ) 当前变量的值就蛮有趣的,明明是i++,现在却是一个负数!为什么呢? 然后要退出当前调试的话,怎么办?分两步: 1. 执行 detach 指令,使 GDB 调试器和程序分离; ) 2. 执行 quit(或 q)指令,退出 GDB 调试。 #### core文件调用 也就是程序执行发生了异常崩溃,这种情况常见与空指针、内存泄漏、野指针等情况。对于linux系统和Android系统都可以使用core dump来调试。core dump是内核的一种转储机制,当程序发生异常的时候,就将发生异常时候的寄存器信息,内存信息都保存下来。 ##### core dump功能 不过此功能在Android的user版本和一般用户的linux发行版当中都是没有打开的,可以通过`ulimit -a` 指令来看系统是否打开: ) ##### 产生core dump文件 手动写一个野指针的例子看一下: ```c #include
int main() { char *p = NULL; *p = 123; return 0; } ``` 编译`gcc -g main.c -o main.out` 执行`./main.out` 之后产生段错误,并提示core文件已转储。段错误又称为访问权限冲突,指的是当前程序访问了不可访问的存储空间,比如访问的不存在的空间,又或者是受系统保护的内存空间。 ) 就在同级目录下: ) ##### 使用core调用gdb ``` gdb main.out core ``` ) 会明确告诉你哪里出了问题。 #### 直接使用gdb命令 效果如此: ) 但我们明确的知道现在我们没有绑定任何可执行程序。所以我们需要这么做: ``` file
``` ) 然后就可以进行一些常规的debug了! ### gdb调试器中启动程序 接着上面的动作看,我们通过gdb命令直接进入gdb调试器,然后通过file命令指定了要调试的可执行文件。然后怎么开始运行?gdb中有两种常用的开始运行命令,分别是run和start: - run:开始运行,直到遇到第一个断点 - start:开始运行,进入main函数之后,第一条语句前停止!相当于在第一条语句出设置了断点 ) 因为这个程序存在错误,我们不往下执行了,只需要输入`kill` 便可结束当前运行的程序! ) ### 指定参数 众所周知main函数是可以指定参数的,当某个可执行程序需要指定参数执行的时候就需要: ```gdb gdb main.out --args arg1 arg2 ... ``` 写个程序来看看吧: ```c #include
int print_args(char *str1, char *str2) { printf("%s\n", str1); printf("%s\n", str2); return 0; } int main(int argc, char *argv[]) { print_args(argv[0], argv[1]); return 0; } ``` 显然这个函数需要给main函数多传一个参数才能执行,所以: ``` gdb --args demo.out klelee ``` ) 或许还有别的方法指定参数?如果我是通过gdb命令进来的呢?啊,对了,确实有!通过下面的命令可以再gdb中指定参数: ``` set args
``` 相关应用如下: ) 小秘密:gdb下可以用cd命令哦 )
点赞
1
收藏
0
淘帖
0
────
1
人觉得很赞
────
回复
使用道具
举报
9 回复
电梯直达
倒序浏览
倒序浏览
正序浏览
10
#
iiv
回复
使用道具
举报
2023-9-10 10:28:06
点赞~
回复
评论
使用道具
举报
9
#
496199544
来自手机
回复
使用道具
举报
2023-9-7 09:11:32
随便发的质量都这么好
回复
评论
使用道具
举报
8
#
粉色小风扇
回复
使用道具
举报
2023-9-7 09:10:01
随便发的质量都这么高
回复
评论
使用道具
举报
7
#
开发板
回复
使用道具
举报
2023-9-7 08:52:06
随便发的质量都这么高
回复
评论
使用道具
举报
6
#
爱笑
回复
使用道具
举报
2023-9-7 08:24:43
随便发的质量都这么高
回复
评论
使用道具
举报
用心做好保姆工作
5
#
Ject
回复
使用道具
举报
2023-9-6 22:51:32
随便发的质量都这么高
回复
评论
使用道具
举报
地板
ai_mcu
回复
使用道具
举报
2023-9-6 19:38:47
可乐klelee 发表于 2023-9-6 17:29
今天太忙了,只能随随便便发一篇了
随便发的质量都这么高
回复
评论
使用道具
举报
明天总会更好
板凳
jkernet
来自手机
回复
使用道具
举报
2023-9-6 19:10:18
学习打卡
回复
评论
使用道具
举报
沙发
可乐klelee
楼主
回复
使用道具
举报
2023-9-6 17:29:07
今天太忙了,只能随随便便发一篇了
回复
评论
使用道具
举报
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
立即登录
手机登录
点评
高级模式
本版积分规则
回帖并转播
返回
今日推荐
ONELAB开发套件常见问题Q&A:距离、角度、速度、距离门设置
【九章MCP验证板】开发环境配置教程
AI-WV02-32S 铁板烧焊接翻车
不用写代码,先跑通这两个开源例程,感受毫米波能做什么
【体验】Ai-WV02-32S 这不就跑起来了么
【问题】Ai-WV02-32S 短路
【B站/视频号直播预告】莫工带你跑通 AI→MCP 协议→硬件执行全
📘 一篇帖,把矽典微毫米波开发系列讲清楚
Ai-BV01-32S 参数全解析——一颗语音模组的底牌,规格书里没写的
第十期电子DIY——用 Ai-WV01-32S 打造一个会说话的AI 小玩意
热帖排行
ONELAB开发套件常见问题Q&A:距离、角度、速度、距离门设置
【九章MCP验证板】开发环境配置教程
TB-04模块 从机收不到主机信息
AI-WV02-32S 铁板烧焊接翻车
<Ai-WB2-12F>这个模组请教个问题-FTP下载
不用写代码,先跑通这两个开源例程,感受毫米波能做什么
VC - 02 烧录问题
【体验】Ai-WV02-32S 这不就跑起来了么
统计信息
会员数: 31167 个
话题数: 42249 篇
首页
分类
我的