使用gdb调试多进程多线程代码
gdb简介GDB是GUN开源组织发布的一个强大的UNIX下的程序调试工具。或许,平时大家更加习惯图形界面的调试,比如VS上的IDE调试;但是如果我们在UNIX或Linux下做软件,我们呢就更加需要熟练GDB这个调试工具。GDB调试使用的是DEBUG版本的,而使用gcc或者g++默认生成的可执行文件为release版本,所以在生成可执行文件时,我们需要在命令的尾部加上 -g,这样就可以生成的...
·
##gdb简介
- GDB是GUN开源组织发布的一个强大的UNIX下的程序调试工具。或许,平时大家更加习惯图形界面的调试,比如VS上的IDE调试;但是如果我们在UNIX或Linux下做软件,我们呢就更加需要熟练GDB这个调试工具。
- GDB调试使用的是DEBUG版本的,而使用gcc或者g++默认生成的可执行文件为release版本,所以在生成可执行文件时,我们需要在命令的尾部加上 -g,这样就可以生成的是DEBUG版本下的可执行文件。
##gdb调试代码的基本常用命令
命令 | 作用 |
---|---|
list或l+行号 | 显示从行号开始的源代码(缺省为10行,下面都是) |
list或l+行号 | 显示某个函数的源代码 |
run或r | 运行程序 |
step或s | 单步执行,遇到函数进入 |
next或n | 单步执行,遇到函数不进入 |
break或b + 行号 | 在某一行设置断点 |
break + 函数名 | 在某个函数开头设置断点 |
info break或i b | 查看断点信息 |
d + 断点序号 | 删除序号为n的断点 |
finish或f | 执行到当前函数返回,然后停下来等待命令 |
print或p + 变量名 | 打印变量的值 |
whatis + 变量名 | 查看变量类型 |
backtrace | 查看函数调用的顺序 |
info frame | 查看当前函数调用的栈帧信息 |
info registers | 查看当前寄存器的值 |
info locals | 查看当前局部变量的值 |
##gdb调试多进程
- 在默认情况下是调试多进程程序时GDB会默认调试主进程,但是GDB支持多进程的分别与同步调试。即GDB支持同时调试多个进程,只需要设置follow-fork-mode(默认为parent)和detach-on-fork(默认为on)即可。我们还可以使用catch fork指令,如果fork异常,会停止程序。
- 显示follow-fork-mode信息
show follow-fork-mode
- 显示detach-on-fork信息
show detach-on-fork
follow-fork-mode | detach-on-fork | 说明 |
---|---|---|
parent | on | 只调试父进程(gbb)默认 |
child | on | 只调试子进程 |
parent | off | 同时调试两个进程,gdb跟主进程,子进程block(阻塞)在fork位置 |
child | off | 同时调试两个进程,gdb跟子进程,主进程block在fork位置 |
- 设置follow-fork-mode和detach-on-fork方法
set follow-fork-mode [child]/[parent] //设置为child或者parent
set detach-on-fork [on]/[off]//设置为on或off
gdb调试多线程
- GDB默认支持调试多线程,跟主线程,子线程阻塞在create thread。
命令 | 作用 |
---|---|
info threads | 显示所有可调试的线程,前面标*为当前调试线程 |
thread ID | 切换到指定线程,gdb为每一个线程分配一个ID(与tid不同),编号一般从1开始 |
thread apply ID1 ID2 command | 让一个或者多个线程执行GDB命令command |
thread apply all command | 让所有被调试线程执行GDB命令command |
set scheduler-locking 选项 command | 设置线程是以什么方式来执行命令 |
set scheduler-locking off/on/step | off表示不锁定任何线程,on表示只有当前调试的线程会继续运行,step表示在单步执行时只有当前线程会运行 |
show scheduler-locking | 显示当前模式 |
假设现在一个进程中有三个线程(线程1,2,3),一个主线程,其余为子线程,假设这三个线程都会走到一个函数中,然后我们可以运行这个进程,然后gdb attach pid调试这个进程,然后在该函数下断点,由于线程是由操作系统调用,所以我们不知道谁先走到这个函数触发断点,假设线程2先触发断点,此时该线程被断住(gdb调试的就是该线程),由于scheduler-locking默认为off(不锁定任何线程)所以在该线程断住的时候其他线程还是可以跑的,由于其他线程也会走到该函数,所以也有可能被断住,当我们在调试该线程(2)的时候如果其他线程走到该函数被断住,那么gdb就会切换到其他线程(调试其他线程),我们可以通过set scheduler-locking来避免这种情况,也可以通过thread 2切换到该线程继续调试。如果没有进行任何操作,继续调试(当前假设是线程3触发断点)线程3,那么线程2就会阻塞在线程3打断的那一步,这种情况可以使用thread apply 2 continue(c)来让线程2继续执行。
更多推荐
已为社区贡献1条内容
所有评论(0)