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

结果输出:

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