使用gdb调试多进程多线程程序

时间:2022-02-08 08:29:52

今天我要需做到以下几点:

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 设置断点,可以简写为b
b 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
[breakpoints] [range...]
 disable所指定的停止点,breakpoints为停止点号。如果什么都不指定,表示disable所有的停止点。简写命令是dis.; 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 stepisinextini 单步跟踪一条机器指令,一条程序代码有可能由数条机器指令完成,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寄存器内容,堆栈内容并没有改变,跨函数跳转容易发生错误。