之前写过一篇GDB的基础使用,包括设置断点、打印变量等。
这次我们来看下GDB进阶调试的技巧,从而进一步提高我们的开发效率。
管理断点
打断点估计是我们最常用的调试方法了。
但是在调试大型循环或者频繁调用的函数时,仅仅依靠普通断点会比较低效。
因此,为了能够更精准地控制调试流程,我们可以使用条件断点 。
假设我们有一个循环,需要当变量i
满足 i == 10
时才停下来。
那么我们可以这样设置条件断点:
(gdb) break gdb_break.c:42 if i == 10
这样设置后, GDB 就会在第 42 行上设置断点,并且仅当 i
的值为 10 时才会触发。
有时,当程序停在断点时,我们可能希望 GDB 自动执行一些命令,例如打印变量的值、跳过一些操作,然后继续运行。
这些操作可以通过断点命令 commands
来自动实现:
(gdb) break gdb_break.c:42
(gdb) commands
> print i
> continue
> end
如上设置后,当程序在 42 行触发断点时,GDB 会自动打印 i
的值,然后继续执行。
观测变量
在程序员的世界里,bug总是多种多样的。
例如程序中的某个变量在某一时刻变成了错误的值。
这个时候我们可以使用 **watch
**来跟踪某个变量的变化,看看它是何时、被什么修改了:
(gdb) watch my_var
GDB 会在 my_var
的值发生变化时暂停程序,并告诉我们是哪一行代码修改了这个变量。
如果我们只关心变量被读时发生了什么,可以使用**rwatch
**:
(gdb) rwatch my_var
这个命令会在 my_var
被读取时暂停程序。
查看复杂数据结构
我们可以使用 print
和 display
命令提高查看复杂数据结构的效率。
-
打印出
my_struct
的所有成员值:(gdb) print my_struct
-
打印出
my_struct
中的某个成员值:(gdb) print my_struct.memberA
-
在每次程序停止时自动打印某个成员的值:
(gdb) display my_struct.memberA
查看函数调用栈
当程序崩溃或运行出现异常时, bt
命令可以让我们查看当前的函数调用栈,从而迅速定位是哪个函数、哪一行代码导致了崩溃:
(gdb) bt
如果我们还需要深入某个栈帧查看局部变量,可以使用 frame
命令:
(gdb) frame 3
自动化调试
我们可以编写脚本来进行自动化调试。
例如,我们可以在gdb_commands.txt
文件中写入如下内容:
break gdb_test.c:42
run
print i
continue
然后在 GDB 中使用以下命令加载该脚本即可实现自动化调试:
(gdb) source gdb_commands.txt
总结
在实际工作中,掌握这些高级功能可以大大提高开发和调试效率。如果你还没用过这些功能,不妨在下次调试中尝试一下~
本文首发于微信公众号《Linux在秋名山》,欢迎大家关注~