gdb的简单使用
本例在CentOS7 64位环境下。
将用下面的例子做说明,可以跟着图片一步一步调试。
1.普通传参(例子1)
// 函数参数传递普通值
#include <stdio.h>
void change(int a,int b){
int tmp = a;
a = b;
b = tmp;
}
int main(){
int a = 5;
int b = 3;
change(a,b);
printf("num a = %d \n num b=%d\n",a,b);
}
使用gdb前提:
程序是调试程序,在gcc时加-g
,例如当前代码使用gcc -o main.out -g main.c
进行编译。
启动程序调试:gdb 程序名
开始运行程序:start
展示代码:l
运行下一行:n
注意: 输入n
之后打印的那一行代码,是之后会运行的代码,此时还没有运行。
小技巧: 在使用一次n
之后,需要再运行n
,可以直接按回车,可以省去输入n
的麻烦。这个方法不止适用于n
,其它的指令也是同样的效果(即按回车等于重复执行上一次输入的命令)。
进入函数:s
当程序运行到第16行的时候,如果使用n,会直接运行到下一行(即不会进入函数中),你看不到函数内是如何运行的。所以当运行到函数的时候,需要使用s
进入函数内调试。
获取变量值:p 变量名
前面的序号$1会一直累加,看后面的结果就好。
显示函数堆栈:bt
在进入change函数内调试之后,使用bt
显示栈堆。
栈底是main,栈顶是change,当前正在运行change函数。
at后面是函数所在的文件和所在行数。
切换栈位置,获取栈内变量值:f 堆栈序号
使用f 堆栈序号
切换栈位置;使用bt
可以获得函数栈堆,其中的堆栈序号就是这里的堆栈序号。
切换之后会显示此栈中运行到哪一行,比如图中,运行到main栈中的第16行,change函数。
之后可以用p 变量名
输出当前栈中变量的值(图中有两个p a
,他们代表的变量不是同一个,上面的a是change函数中的,下面的a是main函数中的)。
退出:quit
或ctrl+d
2.指针传参(例子2)
// 函数参数传递指针地址
#include <stdio.h>
void change(int *a,int *b){
int tmp = *a;
*a = *b;
*b = tmp;
}
int main(){
int a = 5;
int b = 3;
change(&a,&b);
printf("num a = %d \n num b=%d\n",a,b);
}
进入函数:s
a,b的值为他们的地址,相差4个字节。
获取指针变量的值:p *指针变量名
注意: 我们使用n
,会显示出一行代码,这行代码是将要运行的(即当前还没有运行),所以*b的值不等于tmp的值。
3.其它笔记
内存最小的单位叫字节Byte(8bit)。
经常这样:计算用二进制,显示用十进制,编程用十六进制。
内存管理:
64位操作系统,使用的内存只要有前面的48位就可以了(0x7fffffffffffffff~0x0)。
上面是高位,下面是低位。
系统内核:
栈:保存函数运行的状态
可分配区域(绿色区域):在堆、栈之间
堆:
数据段:存放全局变量、常量或静态变量
代码段:代码编译后的二进制数据加载到内存中