1,调试多进程或多线程程序我们可以用printf语句打印消息,比如打印一些用的变量.
这种方法的优点是不用借助其他工具就可以对程序的运行进行观察,缺点是插入语句的位置、粒度等都需要调试者自己去权衡,如果插入过多的打印语句,则频繁的IO操作会使程序运行变慢,线程行为改变,有些bug甚至不会再出现。
2 , 使用我们的gdb工具。
在这里我们先列出gdb的一些基本操作:
————————————————————————————————————————————–
使用:需要在源代码⽣生成的时候加上 -g 选项.
开始使用: gdb binFile
退出:ctrl + d 或 quit
调试过程:
l ist/l ⾏行号:显⽰示binFile源代码,接着上次的位置往下列,每次列10⾏行。
list/l 函数名:列出某个函数的源代码。
r或run:运行程序。
s或step:进入函数调⽤用
breaktrace(或bt):查看各级函数调⽤用及参数
info(i) locals:查看当前栈帧局部变量的值
info break :查看断点信息。
finish:执⾏行到当前函数返回,然后挺下来等待命令
print(p):打印表达式的值,通过表达式可以修改变量的值或者调⽤用函数
set var:修改变量的值
quit:退出gdb
break(b) ⾏行号:在某⼀行设置断点
break 函数名:在某个函数开头设置断点
continue(或c):从当前位置开始连续而⾮非单步执⾏行程序
run(或r):从开始连续而非单步执行程序
delete breakpoints:删除所有断点
n 或 next:单条执行。
p 变量:打印变量值
//—————————————————————————————————–
现在我们来分别说如何调试多进程程序与多线程程序。
1,多进程程序比较容易调试。
我们可以使用调试者选项:set follow-fork-mode mode
mode是我们想要跟踪的进程,可选值为father,child.
示例:
源程序:
使用gcc -o test test.c -g
进入调试gdb test
选择模式:set follow-fork-mode child,
在某一行打断点, b 17
运行至断点, r
//选择child模式就表示我们会跟踪子进程,忽略父进程。
这样就可以调试多个进程了。
2,调试多线程程序。
gdp有一组命令可以帮助我们调试多线程程序,这里列举常用的。
info threads显示当前可调式的所有线程。 gdb会为每个线程分配一个id,我们可以用这个id来操作线程。
thread id,调试目标id线程
set scheduler-locking[off|on|step].因为你在调试一个线程时,其他线程也在执行。但有时我们只想让被调试的线程执行。我们可以设置scheduler-locking的值:off表示不锁定,on表示只有当前进程会运行,step表示单步运行时只有当前进程运行。
简单示例:
为了防止在程序到断点时,有线程运行结束,我们在让除主线程之外的所有线程sleep3秒。
编译:gcc -o test test.c -g -lpthread
调试开始:gdb test
打断点,使程序运行到所有线程创建完暂停。
使用info threads 命令获取id。
使用threadid 调试一个线程,注意使用set scheduler-locking on,
如上图我们就已经到了其他线程。
对于linux新手来说,如何熟练的用gdb来调试程序可能是最大的问题,就像我熟悉vs那一套后,对于linux下的调试方法并不是掌握得很熟练,所以以后还是要多加练习。