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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章