对于很多开发者来说,开发过程中难免会遇到各种各样的bug, 所以,每个开发者应该考虑的如何快速高效定位问题原因,而gdb是linux上很实用的调试工具,熟练掌握其调试技巧,将有助于提高解决问题的效率,也是开发者应该掌握的基本技能。
本文首先会讲解三种启动gdb的方式,然后再介绍两种查看堆栈信息的方法,最后再详细说明两种单步调试的实用技巧。
三种启动
通过gdb启动程序,通常有三种方式。下面分别进行讲解说明。
第一种方式是: gdb + 进程名。 编译程序的时候,需要加上-g选项,以便可执行程序中加入符号表信息,方便问题定位。
第二种方式,gdb –symbols=有符号表的进程 –exec=没有符号表的进程。首先创建没有符号表的进程,然后创建带有符号表的进程,最后再启动进程。
第三种方式,gdb -p 进程号。 这个方式也是最多使用的。因为进程崩溃的时候,仍然可以使用该方式,附着gdb到进程中,然后查看堆栈信息。
首先以后台运行的方式启动进程,然后查看进程的进程号,最后执行“gdb -p 进程号”的命令,把gdb附着到进程中,这样就可以很方便进行调试。
两种堆栈
当程序突然崩溃的时候,可以使用gdb附着到程序中,然后执行bt命令来查看最新的堆栈信息,这往往能够很快定位到问题的原因。
如果进程中启动很多线程,那么如何查看每个线程的堆栈信息呢,执行命令thread apply all bt,可以查看当前进程的所有线程的堆栈信息。
两种技巧
第一个技巧就是利用watch来观察某个变量的变化,当watch检测的变量发生变化的时候,gdb就会立即中断。
假设想要检测Fun函数下i_sum的变化情况,那么首先在该处设置断点,然后运行程序。
运行到断点位置的时候,程序停止,那么可以使用p命令打印变量的值,还可以查看变量的地址,最后还可以使用该地址来设置watch的观察点。
第二个技巧就是单步调试,它的好处就是让开发者可以轻松跟踪代码的流程,从而不需要通过添加日志的方式来确定代码的流程。
假设有如下所示的代码段,我们通过单步调试的方式来跟踪代码流程。同样的,通过gdb启动程序,或者程序附着上gdb之后,设置断点,然后从断点处开始跟踪代码流程。
通过命令r启动程序,程序停止在断点处之后,使用n命令(next)进行单步运行,注意该命令不会进入函数内部跟踪。
那么如果想要进入函数,怎么办呢,可以使用s命令(step)来进入函数内部进行单步调试。
如果函数内部太长,不想要跟踪,那么可以输入命令finish, 直接跳出函数,注意该命令会执行完成函数之后,再退出。
而跳出函数,还有另一个命令return, 但是它不会执行完成函数再退出,而是直接退出。
总结
本文梳理了gdb的常用调试技巧,分别从三个方面进行说明,分别为三种启动、两种堆栈以及两种技巧。启动方式比较常用的是采用-p选项,将gdb附着到程序中。查看堆栈信息的命令bt适用于程序崩溃的问题,thread apply all bt命令则可以查看所有线程的堆栈信息。watch命令跟踪变量的变化情况。next则执行单步运行,但是不进入函数内部,step则会进入函数内部; 命令finish可以跳出函数,但是它会执行完成函数之后再退出;而命令return, 则不会执行完成函数,而是马上就退出。
想了解更多精彩内容,快来关注"软件技术分享"!
领取专属 10元无门槛券
私享最新 技术干货