GDB 调试代码--学习记录

目录

一、其他调试代码的工具

二、GDB调试

1、调试准备

2、开始调试

3、调试命令

1.运行程序

2.退出gdb

3.传参

4.查看代码

5.设置或删除断点及相关操作

6.继续运行

7.运行中打印某些值及其类型

8.自动的打印某些值和信息及其相关操作

9.单步调试

10.设置变量的值

11.gdb的图形界面命令

12.用命令查看指针的信息 

13.x命令检测内存中的相关内容

未完待续~~~。


一、其他调试代码的工具

1.strace 、lsof工具也可以调试。

二、GDB调试

1、调试准备

        在使用gdb调试之前,我们需要在使用gcc编译的时候加上 -g选项, 如果你没有-g选项,运行的时候可以看到gdb提示你不能调试。同时对于多个文件,你都要加上-g

2、开始调试

        假设我编译好的文件名为test, 使用gdb ./test 开启调试。我的文件树如下图所示:

3、调试命令

1.运行程序

        我们使用(run or r or start)三个命令可以运行程序, r是run命令的缩写,这个命令就像你运行 ./test 可执行文件一样,顺便说一下这个test 与加了 -g选项的test 是不一样的。运行start命令,会使程序停止在 main函数入口(如果遇到No debugging symbols found in ** 问题的时候,需要看一下-g选项是否生效了, 同时如果你移动了文件,然后在编译,但是你之前编译的中间文件没有删除,你直接make,在使用gdb的时候也会出现这个问题,删掉旧的中间文件就行了)。如下图:

我的makefile如下: 

all:test

test.o:test.c
	gcc -g $^ -c -o $@
sestack.o:sestack.c
	gcc -g $^ -c -o $@
test:test.o sestack.o
	gcc  -g $^ -o $@

2.退出gdb

        使用quit or q来退出gdb

3.传参

        有时候,我们需要通过命令行去传参数,可以使用set args 参数1 参数2 参数3 ...来给程序传参数。

4.查看代码

        你只能查看当前文件的代码, 如果需要查看其他文件的代码,则需切换到其他的文件。使用list or l  来查看当前文件的代码,你可以通过set listsize  20 来修改你每次需要显示的行数为20。如下图:

当前我在test

         接下来我们切换到sestack.c,你可以看到我使用了list   、 list 行号、 list 函数名、 list  文件名:行号。

5.设置或删除断点及相关操作

        有两种断点,一种是常规断点,一种是条件断点。使用break 行号or b 行号 来设置断点。

或者是使用他们在一个函数处设置断点。

        常规断点的使用,如下图所示:

         条件断点的使用如下图所示:

         

        在设置完断点后我们可以通过info b 或者 i b来查看断点的信息。

         我们可以通过delete or del or d  + 断点的编号来删除断点。或者d num1-num4

         我们还可以通过disable(dis) 或者 enable(ena) 来设置断点的有效和无效。(观察Enb这一行)

6.继续运行

        使用continue or c来继续的向下运行。

7.运行中打印某些值及其类型

        使用print or p 来打印我们想打印的值。同时我们还可以设置我们打印时的输出格式。如下表所示:

         我们可以使用ptype 来打印某个变量的类型。

8.自动的打印某些值和信息及其相关操作

        我们使用display可以来展示我们经常需要打印的值。我们也可以通过info display来展示我们需要自动打印的信息。

 我们可以通过undisplay  编号  或者delete display 编号来删除, 当然这里可以展示不打印使用disable 不打印, 使用enable 来打印:

 

9.单步调试

        我们可以用step or s来进行单步调试(s可以进入到函数体的内部),值得注意的时当我们使用单步调试进入一个函数的时候,我们必须使用finish 来跳出函数。

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

          我们也可以使用next or n来向下运行,但是next不会进入函数体内。

        如果我们想跳出某个循环体 ,我们可以使用until ,但是要满足一下的条件:

  • 要跳出的循环体内部不能有有效的断点
  • 必须要在循环体的开始 / 结束行执行该命令

10.设置变量的值

        有时候我们需要设置某个变量的值,来查看程序的行为。我们可以使用set val 变量名=值来设置某个变量的值。

 可以看到我把s指针设置为null后报错了。

11.gdb的图形界面命令

1. 用layout src命令显示源代码窗口。

2.用backtrace命令显示当前调试环境中所有栈帧的信息。栈帧是函数调用时产生的一段内存空间,用于存储函数的参数、局部变量、返回地址等信息。backtrace命令可以帮助你追踪程序执行的路径,找出哪个函数导致了错误或者异常。

3.用layout split显示源代码和汇编代码两个窗口,方便查看每条源代码对应的汇编指令。你可以用方向键或者空格键在不同的窗口中切换。

4.用tui disable退出图形界面。

12.用命令查看指针的信息 

        p /x *p可以查看指针p的信息(如果指针是t那就是 p /x *t,注意/x是输出格式为16进制,如果是/s ,那表示字符串),只要指针是有效的,即指向了一个已分配的内存地址。(下面的待验证)如果指针是无效的,比如是空指针,或者是野指针,那么p /x *p命令会报错,提示无法访问该地址。你可以用info proc mappings命令来查看进程的内存映射,以及哪些地址是有效的。

        你可以通过p /x *p->**,来打印(比如p是个结构体指针)结构体成员信息,注意如果p前面没有*,这是打印地址。(见前面的打印信息小结)。

13.x命令检测内存中的相关内容

        使用的格式是  x/nfu address

        其中 n是一个正整数,表示需要显示的内存单元的个数,也就是说从当前地址向后显示几个内存单元的内容,一个内存单元的大小由后面的u定义。   f 表示显示的格式 。u 表示从当前地址往后请求的字节数。 addr是一个必须的参数,表示要查看的内存地址。可以是一个寄存器名,一个变量名,一个表达式,或者一个常数(只要它能被gdb解释为一个有效的内存地址)。

未完待续~~~。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值