使用 GDB 调试程序一般有三种方式:
- gdb filename
- gdb attach pid
- gdb filename corename
这也对应着本节课的核心内容:
- 直接调试目标程序
- 附加进程
- 调试 core 文件
接下来我们逐一讲解。
2.1 直接调试目标程序
在开发阶段或者研究别人的项目时,当编译成功生成目标二进制文件后,可以使用 gdb filename 直接启动这个程序的调试,其中 filename 是需要启动的调试程序文件名,这种方式是直接使用 GDB 启动一个程序进行调试。注意这里说的启动一个程序进行调试其实不严谨,因为实际上只是附加(attach)了一个可执行文件,并没有把程序启动起来;接着需要输入run 命令,程序才会真正的运行起来。关于 run 命令后面的课程中会详细介绍。上一课的 GDB 调试 hello_server 系列就是使用的这种方式。
假设现在有一个程序叫 fileserver,使用 gdb fileserver 附加该程序,然后使用 run 命令启动该程序。如下图所示:
![54ef21a31448fcb590741b0a68b7fdcf.png](https://img-blog.csdnimg.cn/img_convert/54ef21a31448fcb590741b0a68b7fdcf.png)
2.2 附加进程
在某些情况下,一个程序已经启动了,我们想调试这个程序,但是又不想重启这个程序。假设有这样一个场景,我们的聊天测试服务器程序正在运行,运行一段时间之后,发现这个聊天服务器不能接受新的客户端连接了,这时肯定是不能重启程序的,如果重启,当前程序的各种状态信息就丢失了。怎么办呢?可以使用 gdb attach 进程 ID 来将 GDB 调试器附加到聊天测试服务器程序上。例如,假设聊天程序叫 chatserver,可以使用 ps 命令获取该进程的 PID,然后使用 gdb attach 就可以调试了,操作如下:
[zhangyl@iZ238vnojlyZ flamingoserver]$ ps -ef | grep chatserver
zhangyl 21462 21414 0 18:00 pts/2 00:00:00 grep --color=auto chatserver
zhangyl 26621 1 5 Oct10 ? 2-17:54:42 ./chatserver -d
实际执行如下图所示:
![55a9c582266799f27369f2e971ebb929.png](https://img-blog.csdnimg.cn/img_convert/55a9c582266799f27369f2e971ebb929.png)
通过以上代码得到 chatserver 的 PID 为 26621,然后使用 gdb attach 26621 把 GDB 附加到 chatserver 进程,操作并输出如下:
[zhangyl@localhost flamingoserver]$ gdb attach 26621
Attaching to process 26661
Reading symbols from /home/zhangyl/server/chatserver...done.
Reading symbols from /usr/lib64/mysql/libmysqlclient.so.18...Reading symbols from /usr/lib64/mysql/libmysqlclient.so.18...(no debugging symbols found)...done.
Reading symbols from /lib64/libpthread.so.0...(no debugging symbols found)...done.
[New LWP 42931]
[New LWP 42930]
[New LWP 42929]
[New LWP 42928]
[New LWP 42927]
[New LWP 42926]
[New LWP 42925]
[New LWP 42924]
[New LWP 42922]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Loaded symbols for /lib64/libpthre