目录
- 1.debug和release
- 拓展
 
- 2.如何使用gdb调试
- 3.指令集
我们平常调试C/C++代码大多实在Windows平台下的VS中,在LInux中,我们通常使用
gdb来调试代码,虽然我们很少在LInux上对代码进行调试,gdb在实际的使用中用的较少,但我们必须要懂它,以面对各种环境。本文目的:能够进行基本的掌握单进程程序的调试,即使用VS 2019、VS 2022的基本调试功能,都在Linux上使用gdb实现。
本文会在Linux环境下使用到vim编辑器、make/Makefile、gcc/g++,如果对这三个工具不熟悉,可点击下面的链接,结合本文一起学习。
vim编辑器
make/Makefile
gcc/g++
1.debug和release
在学习Linux下使用gdb调试之前,我们需要掌握以下三个有关debug和release模式的铺垫知识
-  程序的发布方式有两种,debug模式和release模式 debug模式:该模式是程序员编写程序和调试代码的模式,该模式下生成的可执行程序含有调试信息体积要大于release模式生成的可执行程序。 release模式:没有调试信息,对程序做出优化,减小了程序的体积,更适合用户使用。该模式下生成的可执行程序是公司最终要推向市场的,由公司内测试人员测试是否完善,测试通过后推向市场。 - 注意: debug模式下可以调试,release模式下无法调试。
 下图是VS 2019下,两种模式的选择图,需要那种模式选择那种模式即可 
  
 那在Linux下如何进行两个模式的转换呢?
-  Linux下,gcc/g++出来的二进制可执行程序,默认是release模式 - 即 在Linux下,使用常规的指令生成可执行程序为release模式,无法进行调试
 //常规生成 gcc -o 可执行文件名 源代码文件 g++ -o 可执行文件名 源代码文件
-  要使用gdb调试,必须在使用gcc/g++生成二进制程序时,加上 -g选项gcc -o 可执行文件名 源代码文件 -g g++ -o 可执行文件名 源代码文件 -g
下面我们在如下test.c文件下编辑测试代码,进行测试
 
 注意: 第7行代码,在for循环内定义变量i,这种写法是在c99中开始支持的,我使用的gcc/g++编辑器不支持这种写法,需要在执行命令后添加-std=c99,
Makefile文件如下:
 
 若不会使用Makefile文件,可直接使用如下两条指令测试
gcc -o MyTest-debug test.c -g -std=c99     //生成debug模式的可执行文件
gcc -o MyTest-release test.c -std=c99     //生成release模式的可执行文件
首先,测试release模式下,是否可以调试
 
 如上图显示,红色框内,表示没有找到调试符号,无法进行调试。
其次,测试debug模式下,是否可以调试

 没有显示错误信息,可以正常调试
最后: 观察两个可执行文件的体积,明显debug要大于release
 
拓展
我们可以使用readlef指令查看两个可执行文件下的信息,如下:

 我们可以通过该指令,查看两个文件下的debug信息,如下(grep 指令为查找字符串指令):
 
 MyTest-debug文件下找到了debug信息,MyTest-release什么都没有。
2.如何使用gdb调试
调试器的核心工作:定位问题
接下来简绍在Linux下如何使用gdb进行调试,该段落为分步骤讲解,将gdb下的命令总结放在了下一段落。
如果大家对gdb并不属性,按步骤操作即可
-  进入调试 使用 gdb file指令进入调试模式,如下图
  
-  显示要调试的代码 - l/list 行号:显示文件源代码,从输入的行号起,向下列出十行。一般我们在开始调试时,从- l 1开始查看,接着输入- l或- Enter键,即可获得上次查找位置往下的代码
  
 注意: 输入gdb的指令后,- Enter键就会记录。即,输入指令后,接着输Enter键会重复上面的动作。下面的指令也遵循这个规则。
- 在刚进入gdb模式后,单独使用l进行查看,显示的代码为随机的
  
 
-  设置断点 -  break/b 行号:在某一行设置断点如下图,在19行设置断点  
-  break/b 函数名:在某个函数开头设置断点如下图,在addTestTop函数处设置断点  5是addTestTop函数内第一行代码的行号。 
-  break/b 文件名:函数名:多文件时,可使用该方法设置断点
-  info break/b:查看断点信息 当程序运行后,会在断点处停下,在次查看断点,会显示在该断点处停下的次数。  
 注意: 在gdb中断点的序号是增长的,每次使用后会不断增长,直到关闭在开启后,重新从1开始 
-  
-  运行程序 -  r/run:运行程序 - 有断点的情况,运行到断点处停止
  
- 无断点的情况,直接运行完  
 
- 有断点的情况,运行到断点处停止
-  注意: 一次运行是在全部main函数内全部代码运行完后结束,中途遇到断点停下后,进行其他查看指令不会影响此次调试 
 
-  
-  有断点,运行后,逐语句执行 -  s/step:遇到函数,进入函数内部 
 注意: 进入其他函数后,会产生调用链,即一个函数调用另一个函数,接着再去调用其他函数。 可通过 bt指令查看 
-  
-  有断点,运行后,逐过程运行 - n/next即遇到函数不进入函数,直接执行下一条指令
  - 还记得上面说的按Enter键,执行上次执行的指令吗?如果需要调试的的内容过多,按一次s或n后接着按Enter键即可
 
-  删除断点 -  delete/d breakpoints:删除所有断点  
-  delete/d n:删除序号为n的断点  
 
-  
-  打开和关闭断点 当我们不想使用一个断点,也不想删除该断点时使用 -  disable breakpoint 断点序号:关闭断点  
-  enable breakpoint 断点序号:打开断点  
 
-  
-  查看变量 -  p 变量名:这个指令是需要查看的时候输入,不会影响调试,如下我在调试进入addTestTop函数后,执行了几段语句后,查看sum变量的结果,此时sum为6. 
-  这样查看的效率太低,我们在VS中使用调试时,是执行一次相对应的变量随之变化,可以直接查看,该方法需要用户自己调用,不方便,我们可以使用以下的方法 
 
-  
-  跟踪查看变量 -  display 变量名:执行后,该变量在每执行一个语句后,都会显示出来 
-  可以显示内置类型、结构体等自定义类型、stl 
 
-  
-  取消对断点的跟踪 -  undisplay 序号:不想跟踪某变量时使用 
 
-  
-  跳转至指定行 - until 行号:跳转至X行,在我们上面的代码中有一个循环,我们可以使用该指令跳转出循环
  
 
-  将整个函数跑完 - finash:进入一个函数后执行,只执行该函数,执行完后停下
  
-  从一个断点,到下一个断点 -  continue/c:直接运行到下一个断点处 
-  将 util、finish、continue结合后,可实现基本的调试功能
 
-  
-  退出gdb - q/quit:如果正在调试,会提示是否需要退出
  
3.指令集
gdb binFile 退出: ctrl + d 或 quit/q 调试命令:
- list/l 行号:显示binFile源代码,接着上次的位置往下列,每次列10行。
- list/l 函数名:列出某个函数的源代码。
- r或run:运行程序。
- n 或 next:单条执行。
- s或step:进入函数调用
- break(b) 行号:在某一行设置断点
- break 函数名:在某个函数开头设置断点
- info break :查看断点信息。
- finish:执行到当前函数返回,然后挺下来等待命令
- print§:打印表达式的值,通过表达式可以修改变量的值或者调用函数
- p 变量:打印变量值。
- set var:修改变量的值
- continue(或c):从当前位置开始连续而非单步执行程序
- run(或r):从开始连续而非单步执行程序
- delete breakpoints:删除所有断点
- delete breakpoints n:删除序号为n的断点
- disable breakpoints:禁用断点
- enable breakpoints:启用断点
- info(或i) breakpoints:参看当前设置了哪些断点
- display 变量名:跟踪查看一个变量,每次停下来都显示它的值
- undisplay:取消对先前设置的那些变量的跟踪
- until X行号:跳至X行
- breaktrace(或bt):查看各级函数调用及参数
- info(i) locals:查看当前栈帧局部变量的值
- quit:退出gdb


















