(C語言內存十九)C語言野指針以及非法內存操作


野指針

如果一個指針指向的內存沒有訪問權限,或者指向一塊已經釋放掉的內存,那么就無法對該指針進行操作,這樣的指針稱為野指針(Wild Pointer)。

指向沒有訪問權限的內存

請看下面的代碼:

#include <stdio.h>
int main(){
    char *str;
    gets(str);
    puts(str);
    return 0;
}

在GCC下運行,輸入一個字符串后會提示段錯誤(Segment Fault)。在VS下運行,輸入一個字符串后會提示類似下面的錯誤:
image
這是因為,str 是局部變量,它的值是不確定的,是隨機的,不知道指向哪塊內存。一般情況下,這塊內存要么沒有訪問權限,要么還沒有分配,當 gets() 函數試圖將讀取到的字符串寫入這塊內存時,必然會發生錯誤。

當然,如果足夠幸運的話,str 也可能恰好指向一段分配好的、並且有讀寫權限的內存,程序就運行成功了,但這是小概率事件,一般不會發生。

指向釋放掉的內存

請繼續看下面的代碼:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
    char *str = (char*)malloc(20*sizeof(char));
    strcpy(str, "C語言123456");
    puts(str);
    free(str);
    if(str){
        puts(str);
    }
    return 0;
}

運行程序,第一次輸出C語言123456,第二次輸出的是亂碼或者什么也不輸出。這是因為,free() 只是釋放掉了動態分配的內存,但並未改變 str 的值,str 的值不是 NULL,它仍然指向被釋放掉的內存,所以會執行 if 語句里面的 puts() 函數。但由於此時的內存已經被釋放掉了,原來的字符串已經不在了,所以輸出的數據是未知的。

這就提醒我們,使用 free() 釋放內存的同時要將指針置為NULL,否則下次就無法判斷指向的內存是否有效。

還有一種情況是函數外部指針指向函數內部的變量、數組等,請看下面的代碼:

#include <stdio.h>
void func(char **pp);
int main(){
    char *pstr;
    func(&pstr);
    puts(pstr);
    return 0;
}
void func(char **pp){
    char arr[] = "C語言";
    *pp = arr;
}

arr 數組在棧上分配內存,字符串"C語言"就存儲在這里,func() 函數運行結束后,這塊內存被釋放掉,但是函數外部的 pstr 仍然指向這里,所以執行puts(pstr);時,輸出結果是未知的。

規避野指針

要想規避野指針,就要養成良好的編程習慣:

  1. 指針變量如果暫時不需要賦值,一定要初始化為NULL,因為任何指針變量剛被創建時不會自動成為NULL指針,它的缺省值是隨機的。

  2. 當指針指向的內存被釋放掉時,要將指針的值設置為 NULL,因為 free() 只是釋放掉了內存,並為改變指針的值。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM