常见段错误原因总结

常见段错误原因总结

  • 前言
  • 原因汇总
      • 一、段错误究根到底就是访问了非法内存:
      • 二、数组越界
      • 三、scanf错误使用:
      • 四、指针访问只读内存区:

前言

之前写代码的时候总是会出现段错误:segment fault。所以特地来总结一下常见的段错误,方便以后查找原因。

原因汇总

一、段错误究根到底就是访问了非法内存:

这个内存区要么是不存在的,要么 是受到系统保护的,还有可能是缺少文件或者文件损坏。可能的原因包括:
访问代码段(原因经常是指针未初始化指向了错误的位置或解引用空指针)、访问寄存器
例子1:解引用空指针 int *p=NULL; printf("%d\n",*p); //因为内存低地址为代码段,不可访问?
例子2:访问含有非法值得内存 register int p =10; printf("%d\n",*p); //由于register关键字使变量存储到内核寄存器中,因此不能访问。
野指针:即定义指针时并未对其初始化,其指向的的位置式未知的。对野指针解引用可能造成段错误或者导致程序崩溃。
防止方案:1;定义时初始化为NULL 2;解引用前赋值 3;使用完后指向NULL 每次使用指针之前记得赋值就好了

二、数组越界

如:当使用malloc申请了一页内存,但使用却超出了。 越过数组边界写入数据,在动态分配的内存两端之外写入数据,或改写一些堆管 理数据结构(在动态分配的内存之前的区域写入数据)

堆中:p = malloc(256); p[-1] = 0; p[256] = 0; //访问了未知空间的内存
栈中:int *p=NULL; int a[6]; p=a; for(int i=0;i<10;i++){*p++=i;} //stack smashing detected 访问了未知空间的内存

三、scanf错误使用:

int b; scanf("%d",b);//应为scanf("%d",&b);

四、指针访问只读内存区:

如:char *p=“abcddf”; *p=‘A’; //其实本质上错误原因和解引用空指针类似,“abcddf”在被定义时放在了代码段或常量区。
//解决方法是将字符串存到数组中,再将指针指向数组头

这里补充一下程序运行时内存分配:
1 栈区:存放函数运行时产生的临时变量,局部变量、函数的入口参数,返回值和const定义的局部变量,函数结束后由编译器释放。
2 堆区:用于存放程序运行时被动态分配的内存段,一般由程序员手动申请释放malloc申请,free释放。
3 全局区(静态区):全局区用来存储全局变量,主要分为两个段:1. .bss段:该段用于存放未初始化或者初始化为0的全局变量和静态变量(static)
2. .data段:又叫数据段,用于存储初始化不为0的全局变量和静态变量、const定义的全局变量(在.rodata段)
该段在程序结束后由系统释放。
4 常量区:常量字符串就是放在这里的。 程序结束后由系统释放
5 代码区:又叫.text段用于存放函数的代码,部分字符串常量也存在代码段

三个申请内存的函数:
1. void *malloc(unsigned int size); //单位为字节 如要申请200个字节的空间存储int型数据 int *p=(int *)malloc(50 *sizeof(int))
2. void *calloc(unsigned n,unsigned size); //long *buffer; buffer =(long *)calloc(20,sizeof(long)); 获得一块长整型数组空间
3. void *realloc(void *mem_address,unsigned int newsize);//重新分配内存
三种方式,申请成功返回(void *)类型的指针,失败返回NULL;使用完之后切记要free释放

你可能感兴趣的:(嵌入式C)