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

GDB的基本介绍

GDB是GUN开源组织发布的一个强大的UNIX下的程序调试工具。或许,平时大家更加习惯图形界面的调试,比如VS上的IDE调试;但是如果我们在UNIX或Linux下做软件,我们呢就更加需要熟练GDB这个调试工具。

一般来说,GDB主要能够完成以下的几个功能:

①启动你的程序,可以按照你自己的要求随性所欲的运行程序;

②可以让被调试的程序在你自己所定的位置的断点处挺住;

③当程序被停住时,可以检查此时你的程序中所发生的事情;

④动态的改变你程序的执行环境。

GDB调试使用的是DEBUG版本的,所以我们在生产可执行文件时,我们需要在命令的尾部加上 -g,这样就可以生成的是DEBUG版本下的可执行文件。

调试代码的基本命令

命令作用
list或l + 行号显示从行号开始的源代码
list或l + 函数名列出某个函数的源代码
run或r 运行程序
step或s进入函数调用
breaktrace或bt查看各级函数调用及参数
info或ilocals查看当前栈帧局部变量的值
info break查看断点信息
finish执行到当前函数返回,然后停下来等待命令
print或p打印表达式的值,通过表达式可以修改变量的值或者调用函数
break或b + 行号在某一行设置断点
set var修改变量的值
quit退出调试
break + 函数名在某个函数开头设置断点
continue或c从当前位置开始连续而非单步执行调试程序
run或r从开头连续执行程序而非单步执行
delete breakpoints删除断点
delete breakpoints n删除序号为n的断点
disable breakpoints禁用断点
enable breakpoints启用断点
info或i breakpoints查看当前设置了哪些断点
display + 变量名跟踪查看一个变量,每次停下来都显示这个值
undisplay取消先前对那些变量设置的跟踪
until + x跳至第x行
n或next单步执行
p + 变量打印变量值
list或l列出源代码,接着上次的位置往下列,每次列10行
frame或f帧编号,选择栈帧
start开始执行程序,停在main函数第一行语句前面等待命令
call + 函数名强制调用某个函数

GDB调试多进程

在默认情况下是调试多进程程序时GDB会默认调试主进程,但是GDB支持多进程的分别与同步调试。即GDB支持同时调试多个进程,只需要设置follow-fork-mode(默认为parent)和detach-on-fork(默认为on)即可。我们还可以使用catch fork指令,如果fork异常,会停止程序。

follow-fork-modedetach-on-fork说明
parenton只调试主进程(GDB默认)
childon只调试子进程
parentoff同时调试两个进程,gdb跟主进程,子进程block(阻塞)在fork位置
childoff同时调试两个进程,gdb跟子进程,主进程block在fork位置

设置方法: set follow-fork-mode[parent|child] set detach-on-fork[on|off]

显示:show follow-fork-mode show detach-on-fork


下面通过代码来演示


调试步骤:

只调试父进程


只调试子进程(与上面的对比起来看)


下面呢我们开始直接调试两个进程(父进程运行调试,子进程阻塞等待)


最后我们进行子进程运行调试,父进程阻塞等待


GDB调试多线程

在多线程编程时,当我们需要调试时,有时需要控制某些线程停在断点处,有些线程继续执行;有时需要控制线程的运行程序;有时需要中断某个线程,切换到其他线程。这些呢都可以通过gdb来实现。GDB默认支持调试多线程,跟主线程,子线程block在create+thread。

gdb调试一般有两种模式:all-stop模式和no-stop模式(gdb7.0之前不支持no-stop模式)。

1.all-stop模式

在这种模式下,当你的程序在gdb由于任何原因而停止,所有的线程都会停止,而不仅仅是当前的线程。一般来说,gdb不能单步所有的线程。因为线程调度是gdb无法控制的。无论什么时候当gdb停止你的程序,它都会自动切换到触发断点的那个线程。

2.no-stop模式(网络编程常用)

顾名思义,启动不关模式。当程序在gdb中停止,只有当前的线程会被停止,而其他线程将会继续运行。这时候step,next这些命令就只对当前线程起作用。

如果需要打开no-stop模式,可以向~/.gdbinit添加配置文件:


gdb支持的命里有两种类型:前台的(同步的)和后台(异步 )的。区别很简单,同步的在输出提示符之前会等待程序report一些线程已经终止的信息,异步则是直接返回。所以我们需要set target-async 1。set pagination off不要出现 Type <return> to continue 的提示信息 。最后一步是打开。

下面看一下gdb调试多线程常用命令:

命令作用
info threads显示所有可调试的线程
thread ID切换到指定线程,gdb为每一个线程分配一个ID(与tid不同),编号一般从1开始
breakfilename:linenum thread all在所有线程相应行设置断点,注意如果主线程不会执行到该行,并且启动all-stop模式,主线程执行n或s会切换过去
set scheduler-locking off|on\step默认off,执行s或c其它线程也同步执行。on,只有当前相称执行。step,只有当前线程执行
show scheduler-locking显示当前模式
thread apply all command每个线程执行同意命令,如bt。或者thread apply 1 3 bt,即线程1,3执行bt。

通过代码来演示:


调试步骤:

开始调试:


然后开始运行代码:

单步调试:


切换到其他线程:


再切换到其他线程调试:


设置core文件

core的意思是核心,dumped的意思就是抛出,转储,core dumped就是核心转储的意思。当一个进程异常退出前,该进程会抛出当时该程序进程的内存详细情况存储在硬盘上,文件名通常是core,这就叫core dump。

进程异常终止通常是因为代码存在BUG,比如非法内存访问导致段错误,事后可以用调试器检查core文件以查清错误原因,这叫做事后调试。

uname -a 查看机器参数

ulimit -a 查看默认参数

ulimit -c 1024 设置core文件大小为1024

ulimit -c unlimit 设置core文件大小为无限

ulimit -c unlimited 生成core文件,也可以是指定大小,然后使用gdb ./main core启动,bt查看调用栈即可。

eg1(可以快速定位出问题的位置)

gdb a.out core.xxx

where

eg2 (在 gdb 中使用)

(gdb) core-file core.xxx





  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值