gdb基本使用方法

gdb基本使用方法

core dump:

当一个进程要被终止时,可以选择把进程的用户空间内存数据全部保存在磁盘上,文件名通常是core,这叫做core dump(核心转储)。

一、 生成core dump文件

  ulimit -c //查看是否为0
  ulimit -c unlimited //如果为0

这样在程序崩溃以后会在当前目录生成一个core.xxxx的文件


二、调试core dump文件

生成了core.xxx文件以后

gdb ./应用程序  core.xxxx //  就会恢复现场到你的程序崩溃的那一刻
(gdb)bt          		//这个命令会列出程序崩溃时的堆栈信息,一层一层会有标号  #0  #1  #2 .......

如果你要查看某一层的信息,你需要在切换当前的栈,一般来说,程序停止时,最顶层的栈就是当前栈,如果你要查看栈下面层的详细信息,首先要做的是切换到你想看的栈。

(gdb)f  N    //N是你想要切换的栈的标号,达到后可以用  ‘p  变量’  查看变量的值,以查找异常出现的原因

 info args
 打印出当前函数的参数名及其值。
    
info locals
打印出当前函数中所有局部变量及其值。
       
info catch
打印出当前的函数中的异常处理信息。


三、gdb调试基础命令

(1) 前提条件: 可执行文件必须包含调试信息  gcc -g

(2) 启动gdb调试: gdb 文件名
启动时如果需要带有参数:
     gdb --args myexe param1 param2 param3 ...
启动时指定代码搜索路径:
     gdb -d /search/code
进入后,查看当前代码搜索路径:
     show dir
设置代码搜索路径: 
     dir 目录1:目录2:目录3
     其中的 $cdir 叫做编译目录,是代码在编译时记录到程序中的。
     $cwd 表示当前的调试目录,可以通过 cd 命令来修改。
     要注意这个 cd 修改的是 gdb 会话中的当前目录,不会影响启动 gdb 前文件系统中的目录位置。
     查看gdb会话中的当前目录:pwd
替换前代码搜索路径: 
     set substitute from_path to_path

(3) 查看代码命令
	当前文件:
		list 行号(函数名)
	指定文件:
		list 文件名:行号(函数名)
		
(4) 设置断点
	当前文件:
		break <function> 
		在进入指定函数时停住。C++中可以使用class::function或function(type,type)格式来指定函数名。
	指定文件:
		b 文件名:行号(函数名)
	设置条件断点:
		b 行号 if value==23
		监控某一个条件,然后设置断点,如果i不等于10的时候,就设置断点:		watch i != 10	
	查看断点信息:
		info b
	删除所有的断点,输入N,则单独删除标号为N的断点:
		delete (N)  
		清除N上面的所有的断点:	clear  N    
		
(5) 开始调试
	只运行一行代码:start
	继续停靠在下一断点处: continue  -- c
	直接停在断点处: run -- r
	
(6) 单步调试
	进入到函数体: step -- s
	跳出函数体: finish(如果有循环处有断点,需要将断点删掉)
	不进入函数体,输入k就是一次走k步:next -- n(k)
	
(7) 追踪变量
	优化打印格式:set print pretty on 
	自动打印变量的值: display 变量名
	取消变量的追踪: undisplay 编号 
	获取编号: info display
	显示一个变量的类型: whatis  val
	更详细的方式显示变量var的类型:ptype var		//	会打印出var的结构定义
	手动打印变量的值: print -- p	 var
	打印完整的长字符串(打印字符串的时候,有长度限制):set print element 0
	以16进制显示var的值(): p  /x var 			//	 x 16进制、 d 10进制、 t   二进制、c   按字符格式显示变量、 f    按浮点数
	数组:	print *a@10						//	 如果a是一个数组,这样显示数据的10个元素的值
	修改运行时变量的值:print var=10
	
(8) 跳出循环:u(untill)

(9) 执行上一步命令:回车

(10) 退出gdb:quit -- q

(11) gdb中执行shell命令:shell cmd 或者 !cmd


四、多线程调试

(1)info threads
	查看当前调试环境中包含多少个线程,并打印出各个线程的相关信息,包括线程编号(ID)、线程名称等。

(2)thread id
	将线程编号为 id 的线程设置为当前线程。

(3)thread apply id... command
	id... 表示线程的编号;command 代指 GDB 命令,如 next、continue 等。整个命令的功能是将 command 命令作用于指定编号的线程。当然,如果想将 command 命令作用于所有线程,id... 可以用 all 代替。

(4)break location thread id
	在 location 指定的位置建立普通断点,并且该断点仅用于暂停编号为 id 的线程。

(5)set scheduler-locking off|on|step
	使用 GDB 调试多线程程序时,默认的调试模式为:一个线程暂停运行,其它线程也随即暂停;一个线程启动运行,其它线程也随即启动。
	一些场景中,我们可能只想让某一特定线程运行,其它线程仍维持暂停状态。要想达到这样的效果,就需要借助 set scheduler-locking 命令。 此命令可以帮我们将其它线程都“锁起来”,使后续执行的命令只对当前线程或者指定线程有效,而对其它线程无效。
	off:不锁定线程,任何线程都可以随时执行;
	on:锁定线程,只有当前线程或指定线程可以运行;
	step:当单步执行某一线程时,其它线程不会执行,同时保证在调试过程中当前线程不会发生改变。但如果该模式下执行 continue、until、finish 命令,则其它线程也会执行,并且如果某一线程执行过程遇到断点,则 GDB 调试器会将该线程作为当前线程。

(6)show scheduler-locking
	查看各个线程锁定的状态

(7)thread apply all bt
    查看所用线程堆栈信息


五、多进程调试

(1)set follow-fork-mode <mode>
	其中 mode 为设置调试的进程:可以是child,也可以是parent。当 mode 为 parent 时,程序在调用 fork 后调试父进程,子进程不会受到影响。当 mode 为 child 时,程序在调用 fork 后调试子进程,父进程不会受到影响。

(2)show follow-fork-mode
	查看 GDB 中设置的 follow-fork-mode

(3)set detach-on-fork <mode>
	在GDB中调试多进程时,可以只调试一个进程,也可以同时调试两个进程,这个和 GDB 中的 detach-on-fork 的设置有关。mode 可以为 on,也可以为off。当 mode 为 on 时,表示程序只调试一个进程(可以是父进程、子进程),这是 GDB 的默认设置。当 mode 为 off 时,父子进程都在gdb的控制之下,其中一个进程正常的调试,另一个会被设置为暂停状态。

(4)show detach-on-fork
	查看 GDB 中设置的 detach-on-fork 

(5)info inferiors
	查看当前调试的所有的 inferior。
	GDB 将每一个被调试程序的执行状态记录在一个名为 inferior 的结构中。一般情况下一个 inferior 对应一个进程,每个不同的 inferior 有不同的地址空间。inferior 有时候会在进程没有启动的时候就存在。

(6)inferior <num>
	表示切换到 id 为 num 的 inferior。
	inferior 2 --> 切换到 2 号进程。


六、FAQ

1、断点没有生效?

在这里插入图片描述

(1) 可能是你打断点的输入有问题,如将main.cpp写成了mian.cpp
(2) 动态库中的函数,需要加载之后才能知道符号信息。所以,没加载动态库之前,断点设置成函数名,加载之后,可以断在具体的代码位置。

2、每次调试时需要输入很多重复的命令?

可以将重复的命令写入一个cmd.gdb文件中,比如:

set args codegen.json
set print pretty on

然后在gdb命令行中执行:

source cmd.gdb

3、怎样将调试信息输出到其它文件中?

set logging file gdb.out ## 将gdb输出重定向到gdb.out
set logging on			## 打开日志记录
p mystruct			    ## 打印结构体变量
set logging off			## 关闭日志记录 


Note

  • 编译的时候要加入-g选项,才可以对程序进行跟踪
  • 查看helloword是否包含调试信息
    objdump -h helloword
  • gdb调试程序的时候打印变量值会出现“value optimized out ”情况,可以在gcc编译的时候加上 -O0参数项,意思是不进行编译优化,调试的时候就会顺畅了,运行流程不会跳来跳去的,发布项目的时候记得不要在使用 -O0参数项,gcc 默认编译或加上-O2优化编译会提高程序运行速度

参考:gdb调试常用实用命令和core dump文件的生成

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值