gdb 是一个强大的命令行调试工具,下面的内容按照调试一个程序的完整流程展开:启动程序、设置断点、单步执行、查看状态,直到定位问题。
在GDB中运行程序
一、启动程序
如果在启动 gdb 时没有指明程序,可以使用命令 file 或 exec-file 加载程序。
run(r):run(r) 命令使程序启动,可以在 run 命令中指明程序参数;值得注意的是,首次运行 run 后,如果再次执行 run 并且不带参数,会以之前的参数运行程序。
set args:指定程序的参数。set args 后,run 可以不带参数而以指定的参数运行程序。如果 set args 不带参数,则清除程序参数,执行 run 后程序不带参数运行。
在加载程序后,如果程序重新编译,gdb 会根据符号文件的更改时间自动重载加载符号文件,所以,不需要重新加载文件。
start:使用 start 命令使程序停在 main 函数的第一条语句。
二、调试已经在运行的程序
attach pid:从 ps 获得进程号,通过 attach 命令连接到该进程。attach 一个进程后,gdb 首先 stop 该进程,这样就可以设置断点,执行 step、continue 等命令;如果执行 r 命令,会杀掉原来的进程。
detach:释放该进程,原进程会继续执行。
三、调试多个inferiors和程序
gdb 允许在一个会话下调试多个程序,比如一个进程 fork 出两个或者多个进程,或者把当前程序复制出一个副本,这些都是通过 inferior 实现控制。
info inferiors:显示当前管理的 inferiors。
inferior infono:切换到对应的 inferior。
add-inferior [-copies n] [-exec executable]:添加 n(默认为 1)个 inferior,如果指明 executable 文件,可以以后通过 file 加载符号文件。
clone-inferior [-copies n] [infno]:复制编号为 infno(默认为当前)的 inferior。
其它相关命令:
remove-inferiors infnodetach inferior infnokill inferiors infnomaint info program-spaces
四、调试fork
默认情况下,当一个程序 fork,gdb 会跟踪父进程而子进程畅通无阻的执行。如果在 child 中设置了一个断点,执行到断点处,child 会收到一个 SIGTRAP 信号,默认为终止程序。
最开始调试 child 进程的方法是在 child 中设置一个 sleep,然后通过 attach 连到 child。
set follow-fork-mode mode、show follow-fork-mode:在 Linux2.5.46 以后,gdb 支持 fork 函数的调试;通过 set follow-fork-mode 命令,设置跟随 parent 还是 child,如果不设置默认为跟随 parent。
set detach-on-fork mode、show detach-on-fork:在 Linux,可以通过 set detach-on-fork off 命令,在 fork 后,对 parent 和 child 都进行调试。父、子进程为多个 inferiors,参见第三部分。
五、多线程调试
info threads:显示线程信息。
thread thread-id:切换到对应线程。
thread name [name]:修改当前 thread 的名称。默认为程序名称。
六、Checkpoint
在 Linux,gdb 支持保留程序在某个时候的快照,除了进程号和已经输出的内容,所有状态恢复到快照状态。
通过以下命令实现快照:
checkpoint:生成当前状态的快照info checkpoint:显示快照信息restart checkpoint-id:恢复到某个 checkpointdelete checkpoint checkpoint-id:删除某个 checkpoint