C语言进阶41:内存操作经典问题《一》——野指针

野指针:
指针变量中的值是非法的内存地址,进而形成野指针
野指针不是NULL指针,是指向不可用内存地址的指针
NULL指针并不危害,很好判断,也很好调试

C语言中无法判断一个指针所保存的地址是否合法

一个指针指向malloc申请的内存地址,其实指针是有效的,但是调用free后,这个地址将返还给内存,这个地址将不可用指针将变成野指针。

野指针的由来:

局部指针变量没有被初始化(指针变量定义的时候应该被初始化为NULL)
指针所指向的变量在指针之前被销毁
使用已经释放过的指针
进行了错误的指针运算
进行了错误的强制类型转换

局部变量的地址和局部数组在函数调用之后就被摧毁,如果指针指向原来的变量或者数组,就会形成野指针

实例分析:

#include <stdio.h>
#include <malloc.h>

int main()
{
    int* p1 = (int*)malloc(40);
    int* p2 = (int*)1234567;	//错误的强制类型转换,但此时不会产生程序崩溃,取决的何时使用p2
    int i = 0;
    
    for(i=0; i<40; i++)			//指针运算产生野指针,改写了非法的内存地址
    {
        *(p1 + i) = 40 - i;		//出现越界:错误的指针运算。操作了没有申请的内存空间(非法的内存地址)
    }

    free(p1); 					//释放空间 但不负责将p1重置为空指针或者为任何的地址值
    
    for(i=0; i<40; i++)
    {
        p1[i] = p2[i];			//段错误  使用已经释放过的指针
    }
    
    return 0;
}
基本原则:
绝不返回局部变量和局部数组的地址
任何变量在定义后必须0初始化
字符数组必须确认0结束符后才能成为字符串
任何使用与内存操作相关的函数必须指定长度信息(确定长度信息相等)

#include <stdio.h>
#include <string.h>
#include <malloc.h>

struct Student
{
    char* name;		//局部指针应初始化
    int number;
};

char* func()
{
    char p[] = "D.T.Software";
    
    return p;		//返回一个局部数组
}

void del(char* p)
{
    printf("%s\n", p);
    
    free(p);
}

int main()
{
    struct Student s;		//未初始化指针,产生野指针
    char* p = func(); 		//野指针 
    
    strcpy(s.name, p); 		//name也是野指针:s内的指针未初始化则为野指针。 使用了野指针
    
    s.number = 99;
    
    p = (char*)malloc(5);
    
    strcpy(p, "D.T.Software");		//内存越界 :本质是对野指针进行了操作
    
    del(p);
    
    return 0;
}

可更改为:

struct Student
{
    char* name;
    int number;
};

char p[] = "D.T.Software";
char sp[] = "willwilling";

void del(char* p)
{
    printf("%s\n", p);
    
    free(p);
}

int main()
{
    struct Student s = {sp, 0};

    char* pp = p;
    
    printf("p  = %p\n", p);
    printf("pp = %p\n", pp);
    
    printf("pp = %s\n", pp);
    
    strcpy(s.name, pp); 
    
    //s.name = pp;    
    s.number = 99;
    
    pp = (char*)malloc(20);
    
    strcpy(pp, "D.T.Software");
    
    del(pp);
    
    return 0;
}


猜你喜欢

转载自blog.csdn.net/qq_28388835/article/details/80375154