目录
1.gdb调试工具背景
程序发布方式有两种,debug模式和release模式,Linux中gcc/g++出来的是二进制城区,默认是release模式。但是调试只有debug下才能调试,所以在用gdb调试的时候需要加上-g选项,必须在源代码生成二进制程序的时候,加入一些debug信息才能进行调试。
[wjy@VM-24-9-centos test01]$ gcc mytest.c -o mytest -g
这里发现,加入debug信息的mytest比release下的mytest1文件要大,说明加入了debug。
[wjy@VM-24-9-centos test01]$ readelf -S mytest
通过readelf命令,可以看到mytest下确实加入了debug信息。
2.gdb一些常见命令的使用
- ctrl + d或quit : 推出gdb调试模式
- list/l : 显示binFile源代码,接着上次位置往下列,每次列10行
- run/r : 运行程序,就类似于vs2013中的开始执行不调试
- next/n : 单条执行
- step/s : 进入函数调试
- break/b 行号 : 在某一行设置断点,类似vs2013的F9打断点
- info break : 查看断点信息
- finish : 执行到当前函数返回,然后挺下来等待命令
- print/p : 打印表达式的值,通过表达式可以修改变量的值或者调用的函数
- 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 : 查看当前栈帧局部变量的值
对于这些指令,可通过一个代码例子来具体化。用数字的累加来举例,要求1加到100的总和
[root@VM-24-9-centos test01]# cat mytest.c
#include <stdio.h>
int SumTop(int top)
{
int sum = 0;
for(int i=1;i <= top;i++)
{
sum += i;
}
return sum;
}
int main()
{
int top=100;
int result = SumTop(top);
printf("result = %d\n",result);
return 0;
}
[root@VM-24-9-centos test01]# gcc mytest.c -o mytest -std=c99
>>list会显示调试代码的内容,一次10行,如果想从第一行看的话,那么list + 行号。也可以根据函数名查找list+函数名(如list main)
>>想要打断点,直接b+行号,可以显示打的第几个断点,断点的文件地址以及断电的行号
>>查看断点信息,info b命令,查看你所有打的断点信息
>>run命令就会执行断点出的代码
(gdb) r
Breakpoint 1, main () at mytest.c:16
16 int result = SumTop(top);
>>想要逐语句调试语句,使用step/s命令,类似F11
>>逐过程调试代码,使用n命令,类似F10
>>想要看当前调试时某个变量的值,使用display 变量名命令,查看sum的地址运用diaplay &sum,继续调试每次都能显示变量值,这个就是长显示。
只显示一次的话,运用p 变量名,大小写都是可以的
如果不想长显示某个变量,不能用undisplay + 变量名形式,因为显示变量时,前面都会有一个编号,需要根据这个编号取消长显示,undisplay + 编号。
取消多个长显示,undisplay 编号① 编号②
>>如果在调试过程中进入了这段代码,而发现这段代码是没有错误的,想要跳出这段代码,运用finish命令,结束这一段代码,并打出返回值。
>>上面想要结束一段代码进程还有一种方法,就是再这个函数的下一行代码打一个断点,然后直接跳到下一个断点处。如果想从一个断点直接运行到下一个断点,运用continue/c命令。
这里我们在18行打一处断点,用info b命令查看断点信息,r(run)重新调试一下,进入到第一个断点代码段,发现自己反悔了,这时,想要进入到下一个断点,输入continue命令。
>>在一段函数的内部,如下,如果想要从循环直接跳到return sum;这行代码,也就是不执行for循环,直接运行return,使用until 行号命令。这里面当然前面的for循环也会执行完成。
>>如果删除断点,delete/d 断点编号,注意的是,这里不是代码行好,而是他在info b下显示的序列号。
>>如果要禁用断点,disable 断点编号,发现断点禁用从yes变为no.
想要再次放开断点权限,运用enable 断点编号
>>bt调用堆栈
>>在vs2013下调试的时候是可以修改变量值的,那么同样gdb下也可进行此操作,进入该条语句,使用set var 变量=变量值,进行修改。