野指针概述

野指针通常指的是指针变量中保留的值不会死一个非法的内存地址,但又对其拜访。须要留神的是野指针不是空指针,而是指向内存不可用的指针。
C语言中对于空指针(NULL)是能够判断进去的,然而野指针是无奈判断一个非空指针是否为野指针。
 
野指针个别的起源如下:

部分指针变量没有初始化

#include <string.h>int main(){    char *p;    strcpy(p,"haha"); // 野指针    return 0;}

应用已开释的指针

int main(){    int *p = (int *)malloc(sizeof(int)*5);     free(p);     *p = 1; // 野指针     return 0;}

指针所指向的内存空间在应用前被销毁

#include<stdio.h>char *fun(){    char p[] = "haha";     return p;} int main(){    char *p = fun();     printf("%s\n",p); // 野指针     return 0;}

指针经典谬误

①被指向的变量没有初始化
②没有为指针指向的内存调配足够的内存

struct Demo{    int *p;} int main(){    struct Demo d1,d2;     int i;     for(i = 0; i < 10; i++){        d1.p[i] = i; // 未初始化    }     d2.p = (int *)calloc(5,sizeof(int));    for(i = 0; i < 10; i++){        d2.p[i] = i; // 越界,没有调配足够的空间    }     free(d2.p);     return 0;}

内存调配胜利但没有初始化

#include<stdio.h>#include<malloc.h>int main(){    char *s = (char *)malloc(10);    printf("%s\n",s); // 字符串以 '\0' 为结束符,如不初始化,则未知 '\0'在哪。    free(s);     return 0;}

数组越界

#include<stdio.h> void fun(int a[10]){    int i;     for(i = 0; i < 10 ;i++){        a[i] = i; // 越界        printf("%d\n",a[i]);    }} int main(){    int a[5];     fun(a);     return 0;}

内存透露

void fun(unsigned int size){    int *p = malloc(sizeof(int) * size);    int i;     if(size % 2 != 0){        return ; // 未开释已申请的内存    }     for(i = 0; i < size ;i++){        p[i] = i;        printf("%d\n",p[i]);     }     free(p);}

此处可表明,函数设计时最好是单入口单进口。


屡次对指针进行内存开释

void fun(int *p,int size){    int i;     for(i = 0; i< size; i++){        p[i] = i;        printf("%d\n",p[i]);    }     free(p);} int main(){    int *p = (int *)malloc(5 * sizeof(int));    fun(p,5);     free(p); // 屡次开释     return 0;}

此处能够表明在进行内存操作时,其准则是“谁申请,谁开释”,并且在开释后对指针置空。


应用已开释的指针

void fun(int *p,int size){    int i;     for(i = 0; i < size ;i++){        printf("%d\n",p[i]);    }     free(p);} int main(){    int *p = malloc(5 * sizeof(int));    int i = 0;     fun(p,5);     for(i = 0;i < 5 ; i++){        p[i] = i; // 内存空间已开释    }     return 0;}

内存应用个别规定

① 应用malloc等申请内存后,必须立刻查看返回值是否为NULL;
② 牢记数组长度,避免越界操作,可思考应用柔性数组;
③ 内存申请和开释操作必须匹配,避免内存透露也可避免屡次开释;
④ 如必须在某个函数中开释一个内存,则倡议增加一个参数选项,来显式揭示调用者是否开释内存;
⑤ free后立刻将其赋值为NULL,因为free的参数为空时是非法参数;

email: MingruiZhou@outlook.com