关闭
搜索
搜索
本版
帖子
用户
热搜:
程序员
简洁模式
高级模式
用户组: 游客
消息
提醒
新听众
我关注的
帖子
道具
勋章
任务
设置
退出
请
登录
后使用快捷导航
没有帐号?
立即注册
设为首页
收藏本站
开启辅助访问
切换到窄版
登录
or
立即注册
快捷导航
搜索
首页
论坛
BBS
MCU单片机技术
程序员交流
学习使用GDB调试代码|Linux中国
[复制链接]
作者:
JasonSWK
版块:
›
嵌入式操作系统
›
linux
发布时间:
2021-3-16 21:18:36
1763
0
返回列表
JasonSWK
当前离线
中级会员
中级会员, 积分 291, 距离下一级还需 209 积分
中级会员
中级会员, 积分 291, 距离下一级还需 209 积分
积分
291
发消息
楼主
电梯直达
JasonSWK
发表于 2021-3-16 21:18:36
|
只看该作者
|
倒序浏览
|
阅读模式
导读:
使用 GNU 调试器来解决你的代码问题。
本文字数:6312,阅读时长大约:8分钟
作者:Seth Kenlon
译者:Xingyu.Wang
GNU 调试器常以它的命令gdb称呼它,它是一个交互式的控制台,可以帮助你浏览源代码、分析执行的内容,其本质上是对错误的应用程序中出现的问题进行逆向工程。
故障排除的麻烦在于它很复杂。GNU 调试器并不是一个特别复杂的应用程序,但如果你不知道从哪里开始,甚至不知道何时和为何你可能需要求助于 GDB 来进行故障排除,那么它可能会让人不知所措。如果你一直使用print、echo或printf 语句来调试你的代码,当你开始思考是不是还有更强大的东西时,那么本教程就是为你准备的。
有错误的代码
要开始使用 GDB,你需要一些代码。这里有一个用 C++ 写的示例应用程序(如果你一般不使用 C++ 编写程序也没关系,在所有语言中原理都是一样的),其来源于猜谜游戏系列中的一个例子。
这个代码示例中有一个 bug,但它确实可以编译(至少在 GCC 5 的时候)。如果你熟悉 C++,你可能已经看到了,但这是一个简单的问题,可以帮助新的 GDB 用户了解调试过程。编译并运行它就可以看到错误:
排除段故障
从这个输出中,你可以推测变量 的设置是正确的,因为否则的话,你就不会看到它后面的那行代码执行。当然,这并不总是正确的,但这是一个很好的工作理论,如果你使用 作为日志和调试器,基本上也会得出同样的结论。从这里,你可以假设 bug 在于成功打印的那一行之后的某行。然而,不清楚错误是在下一行还是在几行之后。
GNU 调试器是一个交互式的故障排除工具,所以你可以使用gdb命令来运行错误的代码。为了得到更好的结果,你应该从包含有调试符号的源代码中重新编译你的错误应用程序。首先,看看 GDB 在不重新编译的情况下能提供哪些信息:
当你以一个二进制可执行文件作为参数启动 GDB 时,GDB 会加载该应用程序,然后等待你的指令。因为这是你第一次在这个可执行文件上运行 GDB,所以尝试重复这个错误是有意义的,希望 GDB 能够提供进一步的见解。很直观,GDB 用来启动它所加载的应用程序的命令就是 。默认情况下,GDB 内置了一个断点,所以当它遇到你的应用程序的 函数时,它会暂停执行。要让 GDB 继续执行,使用命令 :
毫不意外:应用程序在打印 “Hello world” 后不久就崩溃了,但 GDB 可以提供崩溃发生时正在发生的函数调用。这有可能就足够你找到导致崩溃的 bug,但为了更好地了解 GDB 的功能和一般的调试过程,想象一下,如果问题还没有变得清晰,你想更深入地挖掘这段代码发生了什么。
用调试符号编译代码
要充分利用 GDB,你需要将调试符号编译到你的可执行文件中。你可以用 GCC 中的 选项来生成这个符号:
将调试符号编译到可执行文件中的结果是得到一个大得多的文件,所以通常不会分发它们,以增加便利性。然而,如果你正在调试开源代码,那么用调试符号重新编译测试是有意义的:
用 GDB 调试
加载新的可执行文件(本例中为 )以启动 GDB:
如前所述,使用 命令进行:
这一次,自动的 断点可以指明 GDB 暂停的行号和该行包含的代码。你可以用 恢复正常操作,但你已经知道应用程序在完成之前就会崩溃,因此,你可以使用 关键字逐行步进检查你的代码:
从这个过程可以确认,崩溃不是发生在设置 变量的时候,而是执行 行的时候。这个 bug 在本文中已经暴露了好几次(破坏者:向 提供了错误的数据类型),但暂时假设解决方案仍然不明确,需要进一步调查。
设置断点
一旦你的代码被加载到 GDB 中,你就可以向 GDB 询问到目前为止代码所产生的数据。要尝试数据自省,通过再次发出 命令来重新启动你的应用程序,然后进行到第 11 行。一个快速到达 11 行的简单方法是设置一个寻找特定行号的断点:
建立断点后,用 继续执行:
现在暂停在第 11 行,就在 变量被设置之后,以及 被设置之前。
用 GDB 进行变量自省
要查看一个变量的值,使用print命令。在这个示例代码中, 的值是随机的,所以你的实际结果可能与我的不同:
当然,你无法看到一个尚未建立的变量的值:
使用流程控制
要继续进行,你可以步进代码行来到达将 设置为一个值的位置:
另外,你也可以设置一个观察点,它就像断点一样,是一种控制 GDB 执行代码流程的方法。在这种情况下,你知道 变量应该设置为 ,所以你可以设置一个观察点,当 的值发生变化时提醒你:
你可以用 手动步进完成代码的执行,或者你可以用断点、观察点和捕捉点来控制代码的执行。
用 GDB 分析数据
你可以以不同格式查看数据。例如,以八进制值查看 的值:
要查看其在内存中的地址:
你也可以看到一个变量的数据类型:
用 GDB 解决错误
这种自省不仅能让你更好地了解什么代码正在执行,还能让你了解它是如何执行的。在这个例子中,对变量运行的 命令给了你一个线索,即你的 和 变量是整数,这可能会唤起你对 语法的记忆,使你意识到在你的 语句中,你必须使用 来代替 。做了这个改变,就可以让应用程序按预期运行,没有更明显的错误存在。
当代码编译后发现有 bug 存在时,特别令人沮丧,但最棘手的 bug 就是这样,如果它们很容易被发现,那它们就不是 bug 了。使用 GDB 是猎取并消除它们的一种方法。
下载我们的速查表
生活的真相就是这样,即使是最基本的编程,代码也会有 bug。并不是所有的错误都会导致应用程序无法运行(甚至无法编译),也不是所有的错误都是由错误的代码引起的。有时,bug 是基于一个特别有创意的用户所做的意外的选择组合而间歇性发生的。有时,程序员从他们自己的代码中使用的库中继承了 bug。无论原因是什么,bug 基本上无处不在,程序员的工作就是发现并消除它们。
GNU 调试器是一个寻找 bug 的有用工具。你可以用它做的事情比我在本文中演示的要多得多。你可以通过 GNU Info 阅读器来了解它的许多功能:
无论你是刚开始学习 GDB 还是专业人员的,提醒一下你有哪些命令是可用的,以及这些命令的语法是什么,都是很有帮助的。
下载 GDB 速查表
via:http://opensource.com/article/21/3/debug-code-gdb
作者:Seth Kenlon选题:lujun9972译者:wxy校对:wxy
本文由LCTT原创编译,Linux中国荣誉推出
欢迎遵照 CC-BY-NC-SA 协议规定转载,
如需转载,请在文章下留言 “转载:公众号名称”,
我们将为您添加白名单,授权“转载文章时可以修改”。
本帖子中包含更多资源
您需要
登录
才可以下载或查看,没有帐号?
立即注册
收藏
0
相关帖子
•
在linux下实现重定向和文件查找
•
vagrant、docker、virtualbox之间的区别
•
推荐10个不错的网络监视工具,建议收藏!
•
Rust引入Linux内核开发?Google:支持!
•
Nyxt浏览器:一个受Emacs和Vim启发的面向键盘的网页浏览器|Linux中国
•
简单架设LINUXVPS服务器
•
十个问题理解Linuxepoll工作原理
•
2021最新100GJava学习资料,从入门到精通!
•
对话胡伟武:和国产CPU一起突围的20年
•
Linux5.14内核主线预计可与RaspberryPi400兼容
回复
使用道具
举报
返回列表
高级模式
B
Color
Image
Link
Quote
Code
表情
@朋友
您需要登录后才可以回帖
登录
|
立即注册
本版积分规则
发表回复
回帖后跳转到最后一页
快速回复
返回顶部
返回列表