GDB 概述
GDB 是 GNU 开源组织发布的一个强大的 UNIX 下的程序调试工具。也许大多数开发人员比较喜欢那种图形界面方式的,像 VC 、 BCB 等 IDE 的调试,但如果你是在 UNIX 平台下做软件开发,你会发现 GDB 这个调试工具有比 VC 、 BCB 的图形化调试器更强大的功能。所谓 “ 寸有所长,尺有所短 ” 就是这个道理。
一般来说, GDB 可以帮助你完成以下几个方面的功能:
启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。
可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式)
当程序被停住时,可以检查此时你的程序中所发生的事。
动态的改变你程序的执行环境。
从上面看来, GDB 和一般的调试工具没有什么两样,基本上也是完成这些功能,不过在细节上,你会发现 GDB 这个调试工具的强大,大家可能比较习惯了图形化的调试工具,但有时候,命令行的调试工具却有着图形化工具所不能完成的功能。下面我们一一来看。
基础操作
要使用 GDB 调试,需要在编译程序的时候加上 -g 参数,例如:
$ gcc -g test.c -o test
1
启动 GDB 调试 test 程序:
$ gdb test
1
执行 run(简写 r)运行程序,但是通常,你的命令行程序需要带上参数,那么就需要指定参数运行,例如:
(gdb) run -d /dev/mtd2
1
另一种方法是使用 set args,例如:
(gdb) set args -d /dev/mtd2
1
几乎每一次调试,我们都会设置断点,单步运行。GDB 设置断点的方式很灵活,使用 break(简写 b)。
例如,在源程序第 232 行处设置断点:
(gdb) break 232
1
在 function() 函数入口处设置断点:
(gdb) break function
1
如果程序包含多个文件,我们还需要指定源文件,例如在 main.c 文件的第8行设置断点:
(gdb) break main.c:8
1
查看断点信息:
(gdb) info break
1
删除断点使用 delete(简写 d),其后的数字可以通过 info break 查看,例如删除第1个断点:
(gdb) delete 1
1
执行单条语句,也就是单步运行使用 next(简写 n)命令。
继续运行程序,使用 continue(简写 c)命令。
使用 finish 命令退出函数。
当程序在断点处停下来后,我们可能需要打印变量的值, 使用 print(简写 p)命令,可以打印基本类型,也可以打印复合类型,例如:
(gdb) print count
1
很不幸,如果程序出错甚至崩溃,我们应该勇敢地面对它,使用 backtrace(简写 bt)命令查看函数堆栈。例如,我刚遇到了一个“Program received signal SIGSEGV, Segmentation fault.”错误:
(gdb) backtrace
#0 0x4007fc13 in _IO_getline_info () from /lib/libc.so.6
#1 0x4007fb6c in _IO_getline () from /lib/libc.so.6
#2 0x4007ef51 in fgets () from /lib/libc.so.6
#3 0x80484b2 in main (argc=1, argv=0xbffffaf4) at segfault.c:10
#4 0x40037f5c in __libc_start_main () from /lib/libc.so.6
1
2
3
4
5
6
通常,我们只关心自己的代码,因此使用 frame 命令切换到3号堆栈帧(stack frame3),看看程序到底是在哪里崩溃的:
(gdb) frame 3
#3 0x80484b2 in main (argc=1, argv=0xbffffaf4) at segfault.c:10
10 fgets(buf, 1024, stdin)
1
2
3
这样我们就可以定位到程序在 fgets() 函数处遇到了麻烦,对于这个例子,显然我们需要关注 fgets() 的参数,特别是指针类型的变量,因为这很可能是由于访问非法内存导致的。
程序调试完,可以使用 kill(简写 k)杀死当前程序,或者使用 quit(简写 q)退出 gdb 调试。
远程调试
前面例子是使用 gdb 调试本机程序,但是对于嵌入式开发,通常我们使用的是交叉编译环境,这样就会给调试带来一定的麻烦。
有时候我们需要在成品机上进行调试,然而成品机把调试串口裁剪掉了。
另外,嵌入式设备的存储容量有限,但是 gdb 调试过程需要配合源代码进行,因为 gdb 会加载对应的源代码来辅助调试,比如对于要查看一个结构体变量的内部数据时,就会去寻找该结构体在源代码中的具体定义,从而更好地解析每个数据域的内容。
当然我们可以把源代码拷贝到嵌入式设备上,然后调试、修改、调试…… 很快我们就会发现这实在太抓狂了!
因此,我们需要远程调试,通过 gdbserver 工具直接在嵌入式设备中调试程序。为了能够实现远程调试,需要将设备与 PC 连接到同一个网络。
然后在设备端使用 gdbserver 启动一个远程调试会话,还是以我们的 test 程序为例,指定端口为 1234:
# gdbserver :1234 test
1
在 PC 机上则直接输入 gdb 命令启动 GDB 调试工具,然后指定 ip 和端口,连接到设备端进行远程调试:
(gdb) target remote 192.168.3.100:1234
1
接下来就会出现与之前的本地调试一样的提示画面了,后续的操作和本地调试也是一样的,Bingo!
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
2015-06-15 VS2010之MFC串口通信的编写教程--转
2015-06-15 VC++如何在程序中用代码注册和卸载ocx控件(代码)