【Linux】gdb调试多线程与多进程

2019-07-12 19:32发布

前言

在多线程编程时,当我们需要调试时,有时需要控制某些线程停在断点,某些线程继续执行。有时需要控制线程的运行顺序。有时需要中断某个线程,切换到其他线程。这些都可以通过gdb实现。 下图为多线程与多进程调试的通用常用命令,应该熟练掌握下面几种命令的使用。
在这里插入图片描述

gdb调试多线程

多线程调试的主要任务是准确及时地捕捉被调试程序线程状态的变化的事件,并且GDB针对根据捕捉到的事件做出相应的操作,其实最终的结果就是维护一个叫thread list的链表。 下面我们以以下多线程的程序为例,在gdb模式下测试各种命令。 #include #include #include int count = 0; void *pthread_run(void *arg) { int i = 0; while(i < 100) { i++; count += i; } return NULL; } int main() { pthread_t pth1; pthread_t pth2; pthread_create(&pth1,NULL,&pthread_run,NULL); pthread_create(&pth2,NULL,&pthread_run,NULL); pthread_join(pth1,NULL); pthread_join(pth2,NULL); printf("count: %d ",count); return 0; } ① 在编译程序时加上-g。如果没有-g,你将看不见程序的函数名、变量名,所代替的全是运行时的内存地址。使用gdb+可执行程序进入gdb调试模式。
在这里插入图片描述
② list [行号]:表示列出第几行附近的代码,默认显示10行,可以摁下l选项顺次列出(list可缩写为l)。
在这里插入图片描述
③ info break:查看断点信息。break [行号],表示在程序的第几行设置断点(break可简写为b)。
在这里插入图片描述
④ r:即run,表示运行程序。上面设置了断点,因此会在第一个断点处停住。
在这里插入图片描述
⑤ delete [断点号]:表示删除单个断点。delete 1-10:删除一个断点的集合,表示删除1到10所有的断点。
在这里插入图片描述
⑥ n:即next,单步调试模式,表示单条语句执行。
在这里插入图片描述
⑦ p [变量名]:打印变量的值,p为printf的缩写。
在这里插入图片描述
⑧ bt:查看函数的堆栈信息。
在这里插入图片描述
⑨ thread apply all bt:让所有线程都打印堆栈信息。thread apply ID command :让ID线程执行命令command。thread apply all command :让所有线程执行命令command。
在这里插入图片描述
⑩ info threads:显示当前可调试的所有线程,gdb为每一个线程分配一个ID号。*表示正在调试的线程。thread [线程ID]:切换到当前要调试的线程ID。
在这里插入图片描述
⑪ c:continue,与C/C++中的continue完全一致。
在这里插入图片描述
⑫ finish:退出当前函数(本例中为pthread_run)。
在这里插入图片描述
⑬ q:即quit,表示退出gdb模式。
在这里插入图片描述

gdb调试多进程

在Linux(CentOS6.5)默认设置下,调试多进程程序时gdb只会调试父进程,为了可以对父子进程都做到调试,我们需要做一些设置。 follow-fork-mode detach-on-fork 具体说明 parent on 只调试父进程 child on 只调试子进程 parent off 同时调试两个进程,gdb跟父进程,子进程block在fork位置 child off 同时调试两个进程,gdb跟子进程,父进程block在fork位置 ① show follow-fork-mode:查看当前调试的fork模式,如下图,默认为父进程,如果想设置为子进程,可以使用set follow-fork-mode child。
在这里插入图片描述
② show detach-on-fork:查看detach-on-fork的模式。设置为on表示只调试父子进程(与①的设置有关)中的一个,off表示父子进程都在gdb的控制之下,其中一个进程正常调试另一个进程会被设置为暂停状态。
在这里插入图片描述
③ info inferiors:显示gdb调试的所有进程。inferior [进程编号]:可以切换到特定的inferiors进行调试。其中*代表正在调试的进程。
在这里插入图片描述
④ maint info program-spaces:显示当前gdb一共管理了多少地址空间。
在这里插入图片描述
⑤ detach inferior [进程编号]:detach掉某一进程的编号,但是这个进程还存在,让它自由运行完,detach掉的进程会显示null。 ⑥ kill inferior [进程编号]:kill掉某进程,但是此进程还存在,可再次使用run等命令执行它,被kill掉的进程会显示null。 ⑦ remove-inferior [进程编号]:删除某一个inferior。如果该inferior正在运行,则不能删除,因此删除之前必须先kill或detach掉。 ⑧ set schedule-multiple:设置为off表示只有当前的inferior会被执行,设置为on,表示所有执行状态的inferior都会被执行。
在这里插入图片描述
⑨ set print interior-events on/off:用来打开和关闭inferior状态的提示信息。
在这里插入图片描述
当然,gdb多线程的断点、单步调试、运行等命令同样适用于多进程的调试,这里也就不一一列举了。上述仅仅是一些常用命令的举例,想了解其他命令请自己动手尝试。