gdb常用命令及使用gdb调试多进程多线程程序
一、常用普通调试命令
1.简单介绍GDB
介绍: gdb是Linux环境下的代码调试⼯具。
使⽤:需要在源代码⽣成的时候加上 -g 选项。
开始使⽤: gdb binFile
退出: ctrl + d 或 quit

2.调试过程
(1)list命令
- list linenum 显⽰binFile第linenum行周围的源代码,接着上次的位置往下列,每次列10⾏。
- list function 显示函数名为function的函数的源程序
- list 显示当前行后面的源程序
- list - 显示当前行前面的源程序

(2)run或r
- run args run命令可以直接接命令行参数值,也可以在执行run之前通过 set args + 参数值实现。

(3)break(b)
- b linenum 在某行打断点
- b +offset/-offset 在当前行号的前面或后面offset停住
- b filename:linenum 在某文件的某行打断点
- b filename:function 在某文件某个函数入口停住
- b *address 在程序的运行地址处停住
- b 没有参数在下一句停住
- b where if condition 当某个条件满足时,在某一行停住(这个很有用,比如b 10 if ret == 5)
- breaktrace(或bt) 查看各级函数调⽤及参数
- delete breakpoints 删除所有断点
- delete breakpoints n 删除序号为n的断点
- disable breakpoints 禁⽤断点
- enable breakpoints 启⽤断点

(4)单步命令
- step count 一次性执行count步,如果有函数会进入函数
- next count 一次执行count,不进入函数
- finish 运行程序,直到当前函数完成返回,并打印函数返回时的堆栈地址和返回值以及参数信息
- until 退出循环体(尤其是针对for循环这种,很烦的)
(5)continue命令
continue(或c):从当前位置开始连续⽽⾮单步执⾏程序
(6)print(p)命令
- x 按十六进制格式显示变量
- d 按十进制格式显示变量
- u 按十六进制格式显示无符号整型
- o 按八进制格式显示变量
- t 按二进制格式显示变量t 按二进制格式显示变量
- a 按十六进制格式显示变量
- c 按字符格式显示变量
- f 按浮点数格式显示变量
(7)watch命令
- watch expr 为表达式expr设置一个观察点,一旦表达式值有变化,马上停住程序
- rwatch expr 当表达式expr被读时,停住程序
- awatch expr 当表达式的值被读或被写时,停住程序。
- info watchpoints 列出所有观察点(info指令通常可以去套 举例如下,演示观测*i的值,一旦变化停下来:
(8)examine命令
是一个正整数,表示显示内存的长度,也就是说从当前地址向后显示几个地址的内容;f
表示显示的格式,如果地址所指的是字符串,那么格式可以是s,如果地址是指令地址,那么格式可以是i;u
表示从当前地址往后请求的字节数,如果不指定的话,GDB默认是4字节。u参数可以被一些字符代替:b表示单字节,h表示双字节,w表示四字节,g表示八字节。当我们指定了字节长度后,GDB会从指定的内存地址开始,读写指定字节,并把其当作一个值取出来。n、f、u这3个参数可以一起使用,例如命令“x/3uh
0x54320”表示从内存地址0x54320开始以双字节为1个单位(h)、16进制方式(u)显示3个单位(3)的内存。
(9)jump命令
- jump linespec 指定下一条语句的运行点,linespec可以是linenum,filename+linenum,+offset这几种形式
- jump address 跳到代码行的地址
(10)signal命令
(11)set命令
- set args 设置命令行参数
- set env environmentVarname=value 设置环境变量。如:set env USER=benben
(12)call命令
- call function 强制调用某函数
(13)disassemble命令
- info(i) locals: 查看当前栈帧局部变量的值
- info break : 查看断点信息
- info(或i) breakpoints: 查看当前设置了哪些断点
- finish: 执⾏到当前函数返回,然后挺下来等待命令
- set var: 修改变量的值
- display 变量名: 跟踪查看⼀个变量,每次停下来都显⽰它的值
- undisplay: 取消对先前设置的那些变量的跟踪
- until X⾏号: 跳⾄X⾏ 直接回
- n 或 next: 单条执⾏
- p 变量: 打印变量值。
(14)另外一些常用调试命令
until 跳出循环。在执行完循环体内的最后一条语句之后执行 until, 就会执行完循环体到后面的一个语句停下。
finish 跳出当前函数,执行完当前的函数。
tui是一个命令行的界面,能同时把代码显示出来。
二、使用gdb调试core文件
1.认识core文件
2.配置生成core文件
①使用 ulimit -c 查看core开关,如果为0表示关闭,不会生成core文件;
②使用 ulimit -c [filesize] 设置core文件大小,当最小设置为4之后才会生成core文件;
③使用 ulimit -c unlimited 设置core文件大小为不限制,这是常用的做法;
④如果需要开机就执行,则需要将这句命令写到 /etc/profile 等文件。
core文件命名和保存路径:
①core文件有默认的名称和路径;
②自己命名和指定保存路径,可以通过 /proc/sys/kernel/core_pattern 设置 core 文件名和保存路径,方法如下:
echo "/corefile/core-%e-%p-%t" > /proc/sys/kernel/core_pattern
命名的参数列表:
%p - insert pid into filename 添加pid
%u - insert current uid into filename 添加当前uid
%g - insert current gid into filename 添加当前gid
%s - insert signal that caused the coredump into the filename 添加导致产生core的信号
%t - insert UNIX time that the coredump occurred into filename 添加core文件生成时的unix时间
%h - insert hostname where the coredump happened into filename 添加主机名
%e - insert coredumping executable name into filename 添加命令名。
3.调试core文件
(1)方法1: gdb [exec file] [core file] 然后执行bt看堆栈信息(或者where命令)
(2)方法1:gdb -c [core file],然后 file [exec file],最后再使用 bt 查看错误位置
https://blog.csdn.net/sunxiaopengsun/article/details/72974548
三、使用gdb调试多进程多线程程序
1.设置
child on 只调试子进程
parent off 同时调试两个进程,gdb跟主进程,子进程block在fork位置
child off 同时调试两个进程,gdb跟子进程,主进程block在fork位置
设置方法:set follow-fork-mode [parent|child] set detach-on-fork [on|off]
查询正在调试的进程:info inferiors
切换调试的进程: inferior <infer number>
添加新的调试进程: add-inferior [-copies n] [-exec executable] ,可以用file executable来分配给inferior可执行文件。
其他:remove-inferiors infno, detach inferior
2.演示代码
下面这段代码的主要流程就是在main函数中fork创建一个子进程,然后在父进程中又创建一个线程,接着就使用gdb进行调试(block子进程)。
#include <stdio.h>
#include <pthread.h>
#include <sys/types.h>
#include <unistd.h> int main(int argc, const char **argv)
{
int pid;
pid = fork();
if (pid != ) //add the first breakpoint.
Parent();
else
Child();
return ;
} //Parent process handle.
void Parent()
{
pid_t pid = getpid();
char cParent[] = "Parent";
char cThread[] = "Thread";
pthread_t pt; printf("[%s]: [%d] [%s]\n", cParent, pid, "step1"); if (pthread_create(&pt, NULL, (void *)*ParentDo, cThread))
{
printf("[%s]: Can not create a thread.\n", cParent);
} ParentDo(cParent);
sleep();
}
//Parent process handle after generate a thread.
void * ParentDo(char *argv)
{
pid_t pid = getpid();
pthread_t tid = pthread_self(); //Get the thread-id selfly.
char tprefix[] = "thread"; printf("[%s]: [%d] [%s] [%lu] [%s]\n", argv, pid, tprefix, tid, "step2"); //add the second breakpoint.
printf("[%s]: [%d] [%s] [%lu] [%s]\n", argv, pid, tprefix, tid, "step3"); return NULL;
}
//Child process handle.
void Child()
{
pid_t pid = getpid();
char prefix[] = "Child";
printf("[%s]: [%d] [%s]\n", prefix, pid, "step1");
return;
}
如果直接运行程序,那么输出的结果如下:
3.gdb调试
3.1设置调试模式和Catchpoint
设置调试父子进程,gdb跟主进程,子进程block在fork位置。



这时可以另开一个终端,使用如下命令查看当前CentOS系统所有进程的状态:发现父进程PID为10062,通过fork产生的子进程为10065:


同时,可以使用命令cat /proc/10062/status查看当前进程的详细信息:进程PID为10060,它的父进程(即GDB进程)为10062,同时这也是追踪进程ID,线程数Threads为1(共享使用该信号描述符的线程数,在POSIX多线程序应用程序中,线程组中的所有线程使用同一个信号描述符)。

3.2 设置第一个断点
在程序的第46行设置断点,并运行到断点处:


这时再次使用命令pstree -pul查看当前系统进程的状态:发现此时仍然只有父进程13162和子进程13159。


3.3 执行到第一个断点此时如果切换到子进程13162

重新切换到父进程13159

3.4 设置第二个断点并调试
在第50行设置断点继续调试主进程(使父进程产生线程),其中父进程和线程到底是谁先执行是由内核调度控制的。
这时使用命令pstree -pul查看当前系统进程的状态:存在父进程13159和子进程13162以及父进程创建的一个线程14208(线程用大括号{}表示)。
同时,使用命令cat /proc/13159/status查看当前进程的详细信息:进程PID为13159,它的父进程(即GDB进程)为13154,同时这也是追踪进程ID,线程数Threads为2(当前父进程13159+线程14208)。

3.5 查看第二个断点处的调试信息

3.6手动切换到线程
3.7 开始执行第二个断点处的代码
这时使用命令查看当前系统进程的状态:存在父进程13159和子进程13162,其中线程14208已经结束了。
本文部分参考:https://typecodes.com/cseries/multilprocessthreadgdb.html
gdb常用命令及使用gdb调试多进程多线程程序的更多相关文章
- gdb调试多进程多线程程序
一.调试的指令 1.list命令 list linenum 显示程序第linenum行的周围的程序 list function 显示程序名为function的函数的源程序 list 显示当前行后面的源 ...
- gdb常用命令及gdb调试多进程/线程程序&coredump
一.常用普通调试命令 1.简单介绍GDB 介绍: gdb是Linux环境下的代码调试⼯具.使⽤:需要在源代码⽣成的时候加上 -g 选项.开始使⽤: gdb binFile退出: ctrl + d 或 ...
- C 调试 gdb常用命令
gdb常用命令: [root@redhat home]#gdb 调试文件:启动gdb (gdb) l :(字母l)从第一行开始列出源码 (gdb) break n :在第n行处设置断点 (gdb) b ...
- Linux GDB常用命令一栏
Linux GDB 常用命令如下: 1.启动和退出gdb (1)启动:gdb ***:显示一段版权说明: (*** 表示可执行程序名) (2)退出:quit.有的时候输入quit后会出现相关提示:类似 ...
- gdb常用命令记录
gdb常用命令 最近在研究nginx源码,gdb用于调试非常方便,之前这篇有研究过如何使用gdb调试nginx:https://www.cnblogs.com/yjf512/archive/2012/ ...
- GDB常用命令系列
本文由霸气的菠萝原创,转载请注明出处:http://www.cnblogs.com/xsln/p/gdb_instructions.html 本文为索引,请点击以下链接进行阅读: GDB调试原理——p ...
- GDB常用命令使用说明(一)
本文由霸气的菠萝原创,转载请注明出处:http://www.cnblogs.com/xsln/p/gdb_instructions1.html 全部关于gdb的文章索引请点这里 GDB(GNU Deb ...
- gdb 常用命令总结(精优)
格式说明: [xxx]:可选参数,即可以指定可以不指定,实际输入的内容是 xxx <xxx>:占位参数,即必须指定的参数,实际输入的内容是 xxx gdb 常用命令: gdb [file] ...
- Linux调试工具strace和gdb常用命令小结
strace和gdb是Linux环境下的两个常用调试工具,这里是个人在使用过程中对这两个工具常用参数的总结,留作日后查看使用. strace调试工具 strace工具用于跟踪进程执行时的系统调用和所接 ...
随机推荐
- spring cloud微服务搭建第一天
martin fowler大神提出微服务的概念后,各种微服务的技术满天飞,现在用的比较多的是spring cloud和阿里的dubbo,由于dubbo 在16年10月份就停止更新了,这里我们讲解spr ...
- 简易版DES加密和解密详解
在DES密码里,是如何进行加密和解密的呢?这里采用DES的简易版来进行说明. 二进制数据的变换 由于不仅仅是DES密码,在其它的现代密码中也应用了二进制数据,所以无论是文章还是数字,都需要将明文变换为 ...
- Exchanger类详解
Exchanger并发辅助类,允许在并发任务之间交换数据.具体来说Exchanger类在两个线程之间定义同步点.当两个线程到达同步点时,它们交换数据结构.需要注意的是Exchanger类只能同步两个线 ...
- Spring+SpringMVC+MyBatis深入学习及搭建(一)——MyBatis的基础知识
转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6812311.html 1.对原生态jdbc程序中问题总结 1.1 jdbc程序 需求:使用jdbc查询mys ...
- css文字溢出隐藏,及强制断句
只显示一行文字,便溢出隐藏 text-overflow: ellipsis; white-place: nowrap; overflow: hidden; 显示 n 行文字后便溢出隐藏 displa ...
- Fast Fourier Transform ——快速傅里叶变换
问题: 已知$A=a_{0..n-1}$, $B=b_{0..n-1}$, 求$C=c_{0..2n-2}$,使: $$c_i = \sum_{j=0}^ia_jb_{i-j}$$ 定义$C$是$A$ ...
- javascript 面向对象基础 (1)
常见的创建对象的方式有3种: ① 声明变量的方式 var obj1 = { key1: "val1", key1: "val2", show: function ...
- 在Excel上写程序(ExcelEx)
首先要说明的是:Ctrl+D,是执行框选的的扩展函数+号,一个单元格里多个函数用+号分隔*号,相当于链式操作(没法子,公式里不能写"."号) 虽还有很大的局限性,至少很多小程序和数 ...
- 022 component(组件)关联映射
Component关联映射: 目前有两个类如下: 值对象没有标识,而实体对象具有标识,值对象属于某一个实体,使用它重复使用率提升,而且更清析. 以上关系的映射称为component(组件)关联映射 在 ...
- 一个IT人员实用的工具:Tmux
1.Tmux安装 tmux下载地址: http://sourceforge.net/projects/tmux/files/tmux/tmux-1.6/tmux-1.6.tar.gz/download ...

