使用gdb调试的实例:

#include<stdio.h>

voide swap(int* a,int* b)

{

int t=\*a;\*a=\*b;\*b=t;

}

int main()

{

int a=3,b=4;

swap\(&a,&b\);

return 0;

}

1.使用 gcc x.c -g编译程序

2.使用gdb打开exe

3.查看源码 l

设置断点在第k行b k

r来运行

bt查看调用stack,这里如果我们把断点设置在swap函数内

可以看到 :

#0.swap(a=0x22acc,b=0x22ccc):4

                \#1.0x00adasd  in main\(\) at x.c:8

这里 #0,1是stack frame编号,其中因为a,b是指针类型,所以显示的是地址

内存中的每个字节都有一个地址编号,每个变量都有一定的字节,其中第一个字节的地址被称为变量的(首)地址

所以我们对于指针(int*) a我们需要给它赋值的是地址,也就是main中的&a,通过赋值地址,我们可以让声明的指针指向我们存储a变量的内存,然后通过取值操作*a来获取该指针指向的变量。当然指向内存的指针怎么知道该变量取多长这就和我们声明的指针类型有关系,int*的指针就是指向int变量大小的内存块,当a*+1的时候跳过的就是int大小的内存地址;而char*的一个变量的大小就是char所占的字节。

段错误 与栈溢出

编译后的可执行文件里都存储着同一个概念,段。段是指二进制文件内的区域,一般来说程序包括,正文段,数据段和bss段。

正文段存储指令,数据段存储已经初始化的全局变量,bss段存储未初始化的全局变量所需要的空间。

调用栈不存储在可执行文件中,而是在运行时创建,称为堆栈段。和其他段一样,它也有自己的大小,访问越界就会出现段错误。比如没有尽头的递归,每次都会增加一个栈帧,久而久之就会超出访问界限形成栈溢出。

栈的大小与操作系统有关,所以建议把大的全局变量放在main函数外,因为不只是栈帧,所有的局部变量也是放在堆栈段的,栈溢出不见得是递归出错,也有可能是局部变量太大导致的。总之超过了堆栈段的最大限制,就会产生栈溢出。

results matching ""

    No results matching ""