linux GDB调试

本章介绍linux环境下使用gdb调试程序。

1.gdb调试条件
想要程序执行并可gdb调试,必须在编译的时候添加**-g**,例如(C语言):gcc test.c -o test -g

2. gdb命令介绍

2.1 gdb 启动
使用 gdb 可执行程序的名字指令后,可执行程序还没有开始跑起来,需要使用 start或run指令来启动执行程序

$ gdb 可执行程序的名字 //例如上述编译得到的test执行文件:gdb test 

启动gdb, 启动执行程序如下图所示:
在这里插入图片描述

**2.2 gdb 设置参数 **
设置参数需要在启动执行文件之前设置,参数值可通过main函数的参数传递给main

(gsb) set args 参数1 参数2 参数3 .....

2.3 gdb 启动可执行程序
启动可执行程序有star和run两条指令,gdb启动后 启动可执行程序只能执行一次。start和run区别:
start:启动可执行程序执行到main函数便停止程序执行,直到gdb的新指令
run: 启动可执行程序执行到第一个断电便停止程序执行,若没有断点则执行到程序结束

(gdb) start
或
(gdb) run

2.4 gdb 退出
若想退出gdb调制,终端输入quit指令便可退出

(gdb) quit

下列讲解的gdb指令需在gdb 启动可执行程序后才能有效设置

2.5 list 显示文件与切换文件
list指令可以查看当前文件内容(启动执行程序main所在的文件为当前文件),默认查看10行,也可以使用set listsize 行数或set list 行数设置显示行数
显示文件指令操作举例如下:

(gdb) list 			//从第一行开始显示
(gdb) list 行号		//指定这行号对应的上下文代码, 默认情况下只显示10行内容
(gdb) list 函数名	//显示这个函数的上下文内容, 默认显示10行

切换当前文件到指定文件,切换成功后指定文件就变成当前文件,就可以查看该文件的内容了

(gdb) list 文件名:行号		//默认显示10行
(gdb) list 文件名:函数名		//默认显示该函数上下文,共10行

设置显示行数,即更改list默认显示行数

(gdb) set listsize 行数
或
(gdb) set list 行数

查看list一次可显示多少函数

(gdb) show list
或
(gdb) showlistsize

2.6 断点操作
gdb 断电顾名思义就是程序执行到断点处便停止执行,需等待下一步指令程序才能有所响应。相关断点操作都是使用指令break。

2.61 设置断点

//设置当前文件断点
(gdb) break 行号
(gdb) break 函数名  //停止在函数名所在的行号

//设置非当前文件断点
(gdb) break 文件名:行号
(gdb) break 文件名:函数名  //停止在函数名所在的行号

//设置条件断点
** 必须要满足某个条件, 程序才会停在这个断点的位置上
** 通常情况下, 在循环中条件断点用的比较多
(gdb) break 行数 if 变量名==某个值

2.6.2 查看断点

(gdb) info break(gdb) info breakpoints

设置断点和显示断电如下图所示:
在这里插入图片描述
上图中Num ,Enb, What
Num: 断点的编号,删除断点或者设置断点状态的时候都需要使用
Enb: 当前断点的状态,y 表示断点可用,n 表示断点不可用
What: 描述断点被设置在了哪个文件的哪一行或者哪个函数上

2.6.3 删除断点

//需要 info b 查看断点的信息, 第一列就是编号
//删除断点
(gdb) d 断点的编号1 [断点编号2 ...]
# 举例: 
(gdb) delete  1          # 删除第1个断点
(gdb) delete  2 4 6      # 删除第2,4,6个断点

//删除一个范围, 断点编号 num1 - numN 是一个连续区间
(gdb) d num1-numN
//举例, 删除第1到第5个断点
(gdb) d 1-5

2.6.4 设置断点状态
设置断点状态不同于删除断点,无效断点状态后断点任然在当需要的时候可以重新开启使用,而删除则是完完全全消失,需要的时候要重新设置

//由有效变无效状态转变
//让断点失效之后, gdb调试过程中程序是不会停在这个位置的
// disable == dis
//设置某一个或者某几个断点无效
(gdb) disable 断点序号1 断点序号2 ......

//设置连续几个断点无效
(gdb) disable 断点序号1-断点序号n


//由无效变有效状态转变
//设置某一个或者某几个断点由无效变有效
(gdb) enable 断点序号1 断点序号2 ......

//设置连续几个断点由无效变有效
(gdb) enable 断点序号1-断点序号n

2.7 调试命令

2.7.1 继续运行continue
如果调试的程序被断点阻塞了又想让程序继续执行,这时候就可以使用 continue 命令。程序会继续运行,直到遇到下一个有效的断点

(gdb) continue

2.7.2 手动打印信息
当程序被某个断点阻塞之后,可以通过一些命令打印变量的名字或者变量的类型,并且还可以跟踪打印某个变量的值

在 gdb 调试的时候如果需要打印变量的值。如果打印的变量是整数还可以指定输出的整数的格式,格式化输出的整数对应的字符表如下:

格式化字符 (/fmt)	说明
/x	以十六进制的形式打印出整数。
/d	以有符号、十进制的形式打印出整数。
/u	以无符号、十进制的形式打印出整数。
/o	以八进制的形式打印出整数。
/t	以二进制的形式打印出整数。
/f	以浮点数的形式打印变量或表达式的值。
/c	以字符形式打印变量或表达式的值。

print指令语法如下

(gdb) print 变量名

//如果变量是整形,默认输出10进制,若要更改输出类型可执行如下指令
(gdb) print/fmt 变量名 
//如16进制输出,如下
(gdb) print/x 变量名		//   /x	以十六进制的形式打印出整数。

2.7.3 打印变量类型
当调试的时候想知道变量名的类型可以使用ptype指令获取到变量类型,指令操作如下:

(gdb) pypte 变量名

2.7.4 自动打印信息
自动打印信息的指令为display,display与print一样都是打印变量信息,不同在于print执行一次指令只打印一次变量信息,而display指令执行一次则每当程序暂停执行(例如单步执行)时,GDB 调试器都会自动帮我们打印出来。display适合频繁要打印变量信息或表达式的值使用。display指令操作如下

//在变量的有效取值范围内, 自动打印变量的值(设置一次, 以后就会自动显示)
(gdb) display 变量名

// 以指定的整形格式打印变量的值, 关于 fmt 的取值, 请参考 print 命令
(gdb) display/fmt 变量名

2.7.5 查看自动显示列表

(gdb) info display

操作如下图所示:
在这里插入图片描述
Num : 变量或表达式的编号,GDB 调试器为每个变量或表达式都分配有唯一的编号
Enb : 表示当前变量(表达式)是处于激活状态还是禁用状态,如果处于激活状态(用 y 表示),则每次程序停止执行,该变量的值都会被打印出来;反之,如果处于禁用状态(用 n 表示),则该变量(表达式)的值不会被打印。
Expression :被自动打印值的变量或表达式的名字。

2.7.6 取消/删除/禁用自动显示信息
取消/删除/禁用自动显示信息指令操作与断电指令操作相似,只是指令开头不同一样

// 命令中的 num 是通过 info display 得到的编号

(gdb) undisplay num1 num2 ...	//编号可以是一个或者多个
(gdb) undisplay num1-numN	// num1 - numN 表示一个范围
//或
(gdb) delete display num1 num2 ...	//编号可以是一个或者多个
(gdb) delete display num1-numN

//如果不想删除自动显示的变量,也可以禁用自动显示列表中处于激活状态下的变量或表达式
(gdb) disable display num1 num2 ...	//编号可以是一个或者多个
(gdb) disable display num1-numN	// num1 - numN 表示一个范围

//取消禁用自动显示(启用自动显示)指令如下
# 命令中的 num 是通过 info display 得到的编号, 
(gdb) enable  display num1 num2 ...	//编号可以是一个或者多个
(gdb) enable  display num1-numN	// num1 - numN 表示一个范围

2.8 单步调试

当程序阻塞到某个断点上之后,可以通过以下命令对程序进行单步调试:

2.8.1 step
step 命令可以缩写为 s, 命令被执行一次代码被向下执行一行,如果这一行是一个函数调用,那么程序会进入到函数体内部。

//从当前代码行位置, 一次调试当前行下的每一行代码
// 如果这一行是函数调用, 执行这个命令, 就可以进入到函数体的内部
(gdb) step

2.8.2 finish
如果通过 s 单步调试进入到函数内部,想要跳出这个函数体, 可以执行 finish 命令。如果想要跳出函数体必须要保证函数体内不能有有效断点,否则无法跳出。

//如果通过 s 单步调试进入到函数内部, 想要跳出这个函数体
(gdb) finish

2.8.3 next
next 命令和 step 命令功能是相似的,只是在使用 next 调试程序的时候不会进入到函数体内部

//如果这一行是函数调用, 执行这个命令, 不会进入到函数体的内部
(gdb) next

2.8.4 until
通过 until 命令可以直接跳出某个循环体,这样就能提高调试效率了。如果想直接从循环体中跳出,必须要满足以下的条件,否则命令不会生效:
1.要跳出的循环体内部不能有有效的断点
2.必须要在循环体的开始 / 结束行执行该命令

(gdb) until

2.9 设置变量值
在调试程序的时候,我们需要在某个变量等于某个特殊值的时候查看程序的运行状态,但是通过程序运行让变量等于这个值又非常困难,这种情况下就可以在 gdb 中直接对这个变量进行值的设置,或者是在单步调试的时候通过设置循环因子的值直接跳出某个循环,值设置的命令格式为: set var 变量名=值

// 可以在循环中使用, 直接设置循环因子的值
// 假设某个变量的值在程序中==90的概率是5%, 这时候可以直接通过命令将这个变量值设置为90
(gdb) set var 变量名=

3.gdb 常用指令总结

1. gdb 可执行程序				//启动gdb
2. set args 参数1 参数2 ... 	//将参数传给main函数的输入参数argc[]
3. run(缩写r) 	//启动可执行程序(执行到第一个断电便停止运行),程序执行后才能设置断点,参数显示信息等指令操作
4. start		//启动可执行程序(执行到main函数行便停止运行),程序执行后才能设置断点,参数显示信息等指令操作
5. quit(缩写q)	//退出gdb调试
6. list(缩写l)    				// 列出源码默认10行(当前位置的上下共10行)
   list 行号      				// 列出行号上下共10行的源码
   list 函数名    				// 列出函数名上下共10行的源码
   list 文件名:行号      			// 切换至文件名并列出该文件名行号上下共10行的源码
   list 文件名:函数名    			// 切换至文件名并列出该文件函数名上下共10行的源码
   set listsize(缩写list) 行数	//设置显示的行数
7. break(缩写b) 行号	 			//停止在当前文件的行号
   break 函数名					//停止在函数的第一行
   break 文件名:行号				//停止在指定文件的行号
   break 文件名:函数名			// 停止在指定文件的函数的第一行
   break 行数 if 变量名==某个值	//必须要满足某个条件, 程序才会停在这个断点的位置上 通常情况下, 在循环中条件断点用的比较多
   info break 					//查看断点信息
   delete(缩写del或d) 断点编号1 断点编号2 ...... 	//删除指定一个或多个指定编号断点
   delete 断点编号1-断点编号n 						//删除指定范围断点
   disable(缩写dis) 断点编号1 断点编号2 ......	//禁用指定一个或多个指定编号断点
   disable断点编号1-断点编号n 						//禁用指定范围断点
   enable(缩写ena) 断点编号1 断点编号2 ...... 	//启用指定一个或多个指定编号断点
   enable 断点编号1-断点编号n 						//启用指定范围断点   
8. continue(缩写c) 				//程序继续运行,直到遇到下一个断点
9. display 变量名					//变量名自动显示
   display/fmt 变量名 				//若整形变量可指定输出格式输出
   info display 					//查看自动显示列表
   undisplay num1 num2 .... 		//取消指定一个或多个的自动显示
   undisplay num1-numN 				//取消指定范围内的自动显示
   disable display num1 num2 .... 	//禁用指定一个或多个的自动显示
   disable display num1-numN 		//禁用指定范围内的自动显示
10. step	//从当前代码行位置, 一次调试当前行下的每一行代码,会进入函数体内
11. finish	//如果通过 s 单步调试进入到函数内部, 想要跳出这个函数体
12. next	//next 命令和 step 命令功能是相似的,只是在使用 next 调试程序的时候不会进入到函数体内部
13. until	//可以直接跳出某个循环体
14. set var 变量名=// 设置变量的值

参考 链接: https://subingwen.cn/linux/gdb/#5-3-4-until

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值