Linux开发工具 —— 调试器gdb

举报
跳动的bit 发表于 2022/06/21 13:55:38 2022/06/21
【摘要】 五、Linux调试器 —— gdb使用 1、背景这里我们对以下代码不理解,需要调试:对我们编译好的可执行程序 mytest 进行 gdb:这是因为 Linux 中默认生成的可执行程序是 release 版本的, 如果需要 debug 版本,就得加上 -g 选项:Linux 中生成的可执行程序,它的二进制的格式是 elf 的,readelf 可以读取内部的格式:我们可以使用选项 -S 查看可...

五、Linux调试器 —— gdb使用

1、背景

这里我们对以下代码不理解,需要调试:
在这里插入图片描述
对我们编译好的可执行程序 mytest 进行 gdb:
在这里插入图片描述
这是因为 Linux 中默认生成的可执行程序是 release 版本的, 如果需要 debug 版本,就得加上 -g 选项:
在这里插入图片描述
Linux 中生成的可执行程序,它的二进制的格式是 elf 的,readelf 可以读取内部的格式:
在这里插入图片描述
我们可以使用选项 -S 查看可执行程序的分段情况:
在这里插入图片描述
gdb 调试 debug 版本:
在这里插入图片描述

  1. 在 C语言阶段我们就了解过了程序的发布方式有两种,debug 模式和 release 模式
  2. Linux gcc/g++ 出来的二进制程序,默认是 release 模式
  3. 要使用 gdb 调试,必须在源代码生成二进制程序的时候,加上 -g 选项

一个项目的开发流程 ❓
在这里插入图片描述
注意对于上图中的测试来说严格来说并不是测开,如果产品迭代更新,bug 修复等,严格来说就得重新测试,包括上代产品测试过的,这样成本较高,所以就诞生了很多自动化测试的开发需求,这就是测开,所以一般这里成本较低的一些脚本语言做的,如 python。

2、开始使用

ctrl + d/D 或 quit/q:退出调试
list/l 行号(, 行号):显示 binFile 源代码,显示的是当前行号周围的代码,可以利用另一个行号来指定一段区间
list/l 函数名:列出某个函数的源代码
r 或 run:运行程序
n 或 next:单条执行
s 或 step:进入函数调用
break(b) 行号:在某一行设置断点
break 函数名:在某个函数开头设置断点
info break/i b:查看断点信息
finish:执行到当前函数返回,然后停下等待命令
print(p):打印表达式的值,通过表达式可以修改变量的值或调用函数,类似于 p
p/P 变量:打印变量值
set var:修改变量的值
continue 或 c:从当前位置开始连续而非单步执行程序
delete breakpoints/d 或 d:删除所有断点
delete breakpoints n 或 d n:删除序号为 n 的断点
enable (breakpoints) 序号:启用断点,默认全启
disable 序号:禁用断点,默认全禁
display 变量名:跟踪查看一个变量,每次停下来都显示它的值
undisplay:取消对先前设置的那些变量的跟踪
until X 行号:跳至 X 行
breaktrace 或 bt:查看各级函数调用及参数
info (i) locals:查看当前栈帧局部变量的值
quit:退出 gdb

调试代码(入门) ❗

  1. l + 行号(, 行号),显示的是当前行号周围的代码,按回车继续往下显示,直到全部显示完
    在这里插入图片描述

  2. b + 行号,打断点
    在这里插入图片描述

  3. i + b,查看断点
    在这里插入图片描述

  4. r,运行程序(调试)
    在这里插入图片描述

  5. n,单步执行,继续执行可按 n/Enter(gdb 可以记录历史执行的命令)
    在这里插入图片描述

  6. p + 变量,查看变量(监视),当循环往下走时,它不会变化,所以它用于查看一次
    在这里插入图片描述

  7. display + 变量,跟踪查看一个变量,每次停下来都显示它的值

在这里插入图片描述

  1. undisplay + 变量序号,取消对先前设置的那些变量的跟踪

在这里插入图片描述

  1. c,循环还没走完,想直接跳出循环到下一个断点处(因为我已经确定这个循环是对的)
    在这里插入图片描述
  2. 结束调试,使用 ctrl + d 或 quit,退出调试
    在这里插入图片描述

调试代码(进阶),主要演示剩余的指令 ❗
在这里插入图片描述

  1. 设置断点
    在这里插入图片描述
  2. d n,删除序号为 n 的断点;d,删除所有断点
    注意如果删除断点,下一次再加断点,它的 Num 是递增的,除非把 gdb 退出
    在这里插入图片描述
  3. 设置了 17 行和 24 行的断点,并 r,接着 n 往下走执行 scanf
    注意空行会直接跳过

在这里插入图片描述

  1. 这里我们想进入函数内部,先试用 n
    发现它并没有进入,说明 n 是逐过程执行
    在这里插入图片描述

  2. 重新调试可以再 r
    在这里插入图片描述

  3. 这里想进入函数内部可以使用逐语句命令 s

在这里插入图片描述

  1. bt,查看调用堆栈
    在这里插入图片描述

  2. a)现在在 Sum 内的循环里,想跳出循环到 return,Sum 里没断点,不能用 c
    until 行号,跳转到指定行号

在这里插入图片描述

b)现在在 Sum 内的循环里,想跳出到 20 行等待,除了使用 until 外,更规范的的还可以使用 finish,执行到当前函数返回,然后停下等待命令,注意不能 finish main 函数
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

c)现在在 Sum 内的循环里,想跳到下一个断点处可以直接 c
![在这里插入图片描述](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/40509695ebe1480991d0fc6133eaba37~tplv-k3u1fbpfcp-zoom-1.image)
  1. disable (序号),断点禁用,默认是全禁;
    enable breakpoints (序号),断点启用,默认是全启
    在这里插入图片描述

  2. 如果在循环里有 100 次循环,想将循环跑到第 80 次可以 set var
    在这里插入图片描述

📝 小结

最后想必很多同学会觉得 gdb 相比 VS 的调试成本就高的多,其实那是 gdb 用的不熟练导致的,如果熟练了其实可以说它俩的效率是等价的
实际对于 gdb,在往后的编程中用的不多,不用则已,一用惊人,所以还是得了解的。

3、理解

相信大家对 Visual Studio 2017 已经不陌生了,这里为了方便记忆,可以对应 VS 的操作来进行理解记忆

b 行号 ↔ F9 
r ↔ F5
c ↔ F5
n ↔ F10
s ↔ F11
q ↔ shift + F5
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。