free()到底做了什麼

1.問題

在LeetCode上做題偶然發現一道題:free內存後,還繼續調用該指針,於是好奇,想了解free到底做了什麼。

這段代碼的free()掉了nextTemp結點的malloc內存,但後面還可以使用nextTemp = nextTemp->next。

2.原因

2.1 free的實現原理

操作系統在調用malloc函數時,會默認在malloc分配的物理內存前面分配一個數據結構,這個數據結構記錄了這次分配內存的大小,在用戶眼中這個操作是透明的。

那麼當用戶需要free時,free函數會把指針退回到這個結構體中,找到該內存的大小,這樣就可以正確的釋放內存了。

使用Linux的man手冊查看(#man 3  free),只是說分配了之後需要free,並沒有過多的說明:

The  free() function frees the memory space pointed to by ptr,
which must have been returned by a previous call to malloc(), calloc(), or realloc().  
Otherwise, or if free(ptr) has already been called before, 
undefined  behavior  occurs.
If ptr is NULL, no operation is performed.

2.2 回答

找了一些資料,發現的確是可以的,並且編譯也不會報錯,具體原因如下:

1)free只是釋放了malloc所申請的內存,並沒有改變指針的值;

2)由於指針所指向的內存空間已經被釋放,所以其他代碼有機會改寫其中的內容,相當於該指針從此指向了自己無法控制的區域(無法控制這麼說還是可以去使用的,只是危險),也成爲野指針(野指針指指向一個已刪除的對象或未申請訪問受限內存區域的指針。與空指針不同,野指針無法通過簡單地判斷是否爲NULL避免)。

3)爲了避免錯誤,所以最好在free之後,使指針指向NULL。

根據原理的解釋分析:free函數的作用只是告訴操作系統該內存不用了,可以收回,操作系統就把該內存鏈接到鏈接表上,

但是這段內存用戶還是可以訪問到的,只是該內存的值可能已經發生了變化。

  

3.總結

其實,free函數只是將參數指針指向的內存歸還給操作系統,並不會把參數指針置NULL,爲了以後訪問到被操作系統重新分配後的錯誤數據,所以在調用free之後,通常需要手動將指針置NULL。從另一個角度來看,內存這種底層資源都是由操作系統來管理的,而不是編譯器,編譯器只是向操作系統提出申請。所以free函數是沒有能力去真正的free內存的。只是告訴操作系統它歸還了內存,然後操作系統就可以修改內存分配表,以供下次分配。

4.案列

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

int main()
{
    char *str = (char *)malloc(100);
    if(NULL == str)
    {
        printf("malloc failed !\n");
        return 1;
    }

    sprintf(str,"hello world");

    if(str != NULL) {
        printf("%p,%s\n", str,str);
    }

    free(str);

    if(str != NULL) {
        printf("%p,%s\n", str,str);
    }

    str = NULL;
    printf("%p,%s\n", str,str);//這裏把它指向NULL
    /* 這裏驗證str爲NULL時,free多次都是沒有問題的,但不爲NULL,則不行 */
    free(str);
    free(str);

    return 0;
}

結果輸出:

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