一、gdb调试多进程
- 多线程代码
2.默认设置下,在调试多进程程序时GDB只会调试主进程。但是GDB(>V7.0)支持多进程的分别以及同时调试,换句话说,GDB可以同时调试多个程序。只需要设置follow-fork-mode(默认值:parent)和detach-on-fork(默认值:on)即可。
follow-fork-mode 和detach-on-fork 说明
<1>,设置方法:
- set follow-fork-mode[parent|child]
- set detach-on-fork[on|off]
<2>,显示:
show follow-fork-mode show detach-on-fork
调试父进程
<3>,查询正在调试的进程: info inferiors
显示GDB调试的所有inferior,GDB为他们分配ID。其中带*的进程是正在调试的进程。
(GDB将每一个被调试程序的执行状态记录在一个名为inferior的结构中。一般情况下一个inferior对应一个进程,每一个inferior都有自己的地址空间。inferior有时候会在进程没有启动时就存在)
<4>,切换调试的进程: inferior (inferior number)
通过该指令可以切换到ID为number的inferior进行调试。
为了能够在终端长查看两个进程,我们需要多代码进行下断点调试;
- 利用函数名下断点,catch;
- 利用行号下断点,break 文件名:行号;
可以看见有两个进程
再次利用inferior (number)切换回去,运行程序
同理,我们也可以调试子进程
设置
设置断点
调试子进程
<5>,调加新的调试进程: add-inferior[-copies n][-exec executable]
可以用file+executable来分配给inferior可执行文件。+增加n个inferior并执行程序为executable。如果不指定n只增加一个inferior。如果不指定executable,则执行程序留空,增加后可使用file命令重新指定执行程序。这时候创建的inferior其关联的进程并没启动。
<6>,删除一个infnum 的inferior: remove-inferiors infnum (如果inferior正在运行,则不能删除,删除之间需先kill或detach掉该inferior)
<7>,detach掉infnum的inferior: detach inferior infnum 注意( inferior仍然存在,可以用run等命令执行 )
<8>,kill 掉infnum的inferior: kill inferior infnum 注意(inferior仍然存在,可以用run等命令执行
二、gdb调试多线程
1.当需要调试的程序正在运行时,如下例代码:
代码
- 方法一,从新开个终端,在gdb命令行上指定进程的PID;
方法二,在gdb中使用attach命令
两种方法首先都要得到正在执行进程的id号
方法一:gdb 进程id,即可调试进程
方法二:
下面是线程调试的基本方法
2,当需要调试的代码没有正在运行,我们只需要设置断点,根据gdb命令调试即可。
代码示例:
调试过程:
3.总结gdb多线程调试的基本命令
<1>.info threads 显示当前可调试的所有线程,每个线程会有一个GDB为其分配的ID,后面操作线程的时候会用到这个ID。
前面有*的是当前调试的线程。
<2>.thread ID 切换当前调试的线程为指定ID的线程。
<3>.break thread_test.c:123 thread all 在所有线程中相应的行上设置断点
<4>.thread apply ID1 ID2 command 让一个或者多个线程执行GDB命令command。
thread apply all command 让所有被调试线程执行GDB命令command。
<5>.set scheduler-locking off|on|step 估计是实际使用过多线程调试的人都可以发现,在使用step或者continue命令调试当前被调试线程的时候,其他线程也是同时执行的,怎么只让被调试程序执行呢?通过这个命令就可以实现这个需求。
- off 不锁定任何线程,也就是所有线程都执行,这是默认值。
- on 只有当前被调试程序会执行。
- step 在单步的时候,除了next过一个函数的情况(熟悉情况的人可能知道,这其实是一个设置断点然后continue的行为)以外,只有当前线程会执行。