今天我要需做到以下几点:
1. 博客中书写多进程调试代码测试用例
2. 博客中书写多线程调试代码测试用例
3. 对调试指令进行总结
1.首先,其实gdb本身没有对多进程程序调试提供直接支持。例如,使用gdb调试某个进程,如果该进程fork了子进程,gdb会继续调试该进程,子进程会不受干扰地继续运行下去。如果我们事先在子进程代码里设定了断点,子进程会收到SIGTRAP信号并终止。所以我们可以通过去子进程设置断点,再通过step与continue交替运行,找到最终程序错误的原因所在
3.对于调试指令的总结
<img alt="使用gdb调试多进程多线程程序" src="http://img.zhimengzhe.com/d/file/p/2017-06-06/683a305c22265bdf54e39c80cf6fc581.png" args="" 10="" 20="" 30="" 40="" 50="" )
show args
命令可以查看设置好的运行参数。run (r)
启动程序
不指定运行参数r
指定运行参数 r 10 20 30 40 50
info terminal
显示你程序用到的终端的模式。
使用重定向控制程序输出。如:run > outfile
tty
命令可以设置输入输出使用的终端设备。如:tty /dev/tty1
break
设置断点,可以简写为bb 10
设置断点,在源程序第10行b func
设置断点,在func
函数入口处
info b 查询所有断点
watch
为表达式(变量)expr设置一个观察点。当表达式值有变化时,马上停住程序。rwatch
表达式(变量)expr被读时,停住程序。awatch
表达式(变量)的值被读或被写时,停住程序。info watchpoints
列出当前所设置了的所有观察点。
维护停止点:
clear
清除所有的已定义的停止点; clear function
清除所有设置在函数上的停止点; clear linenum
清除所有设置在指定行上的停止点; clear filename:linenum
清除所有设置在指定文件:指定行上的停止点; delete [breakpoints] [range...]
删除指定的断点,breakpoints为断点号。如果不指定断点号,则表示删除所有的断点; range
表示断点号的范围(如:3-7)。其简写命令为d; 比删除更好的一种方法是disable停止点,disable了的停止点,GDB不会删除,当你还需要时,enable即可,就好像回收站一样; disable
disable所指定的停止点,breakpoints为停止点号。如果什么都不指定,表示disable所有的停止点。简写命令是dis.;
[breakpoints] [range...]enable [breakpoints] [range...]
enable所指定的停止点,breakpoints为停止点号; enable [breakpoints] once range…
enable所指定的停止点一次,当程序停止后,该停止点马上被GDB自动disable; enable [breakpoints] delete range…
enable所指定的停止点一次,当程序停止后,该停止点马上被GDB自动删除
调试代码:
run
运行程序,可简写为r next
单步跟踪,函数调用当作一条简单语句执行,可简写为n step
单步跟踪,函数调进入被调用函数体内,可简写为s finish
退出函数 until
在一个循环体内单步跟踪时,这个命令可以运行程序直到退出循环体,可简写为u continue
继续运行程序,可简写为c stepi
或si
, nexti
或ni
单步跟踪一条机器指令,一条程序代码有可能由数条机器指令完成,stepi和nexti可以单步执行机器指令 info program
来查看程序的是否在运行,进程号,被暂停的原因。
查看运行数据:
print
打印变量、字符串、表达式等的值,可简写为p p count
打印count的值 p cou1+cou2+cou3
打印表达式值print
接受一个表达式,GDB会根据当前的程序运行的数据来计算这个表达式,表达式可以是当前程序运行中的const常量、变量、函数等内容。但是GDB不能使用程序中定义的宏。
堆栈相关命令:
backtrace/bt bt 用来打印栈帧指针,也可以在该命令后加上要打印的栈帧指针的个数,查看程序执行到此时,是经过哪些函数呼叫的程序,程序“调用堆栈”是当前函数之前的所有已调用函数的列表(包括当前函数)。每个函数及其变量都被分配了一个“帧”,最近调用的函数在 0 号帧中(“底部”帧);
frame frame 1 用于打印指定栈帧; info reg info reg 查看寄存器使用情况 ; info stack info stack 查看堆栈使用情况 ; up/down up/down 跳到上一层/下一层函数
signal signalSIGXXX 产生XXX信号,如SIGINT。一种速查Linux查询信号的方法:# kill -l
handle 在GDB中定义一个信号处理。信号可以以SIG开头或不以SIG开头,可以用定义一个要处理信号的范围(如:SIGIO-SIGKILL,表示处理从SIGIO信号到SIGKILL的信号,其中包括SIGIO,SIGIOT,SIGKILL三个信号),也可以使用关键字all来标明要处理所有的信号。一旦被调试的程序接收到信号,运行程序马上会被GDB停住,以供调试。其可以是以下几种关键字的一个或多个:
nostop/stop当被调试的程序收到信号时,GDB不会停住程序的运行,但会打出消息告诉你收到这种信号/GDB会停住你的程序;
print/noprint当被调试的程序收到信号时,GDB会显示出一条信息/GDB不会告诉你收到信号的信息;
passnoignore当被调试的程序收到信号时,GDB不处理信号。这表示,GDB会把这个信号交给被调试程序会处理;
nopassignore当被调试的程序收到信号时,GDB不会让被调试程序来处理这个信号;
info signalsinfo handle可以查看哪些信号被GDB处理,并且可以看到缺省的处理方式;
single命令和shell的kill命令不同,系统的kill命令发信号给被调试程序时,是由GDB截获的,而single命令所发出一信号则是直接发给被调试程序的。
跳转执行:jump 指定下一条语句的运行点。可以是文件的行号,可以是file:line格式,可以是+num这种偏移量格式。表式着下一条运行语句从哪里开始。相当于改变了PC寄存器内容,堆栈内容并没有改变,跨函数跳转容易发生错误。