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

结果输出:

free()到底做了什么相关推荐

  1. volatile关键字到底做了什么?

    话不多说,直接贴代码 class Singleton {private static volatile Singleton instance;private Singleton(){}//双重判空pu ...

  2. 忠于职守 —— sysmon 线程到底做了什么?(九)

    在 runtime.main() 函数中,执行 runtime_init() 前,会启动一个 sysmon 的监控线程,执行后台监控任务: systemstack(func() { // 创建监控线程 ...

  3. http.ListenAndServe()到底做了什么?

    参考:https://studygolang.com/articles/25849?fr=sidebar ​ http://blog.csdn.net/gophers 实现一个最简短的hello wo ...

  4. ad中电容用什么封装_二极管在电路中到底做什么用的

    所有的电子电路中基本上都会用到二极管,它的特性也是非常之多,最主要就是单方向导电性,(单向导电性的两根引脚之间的电阻分为正向电阻和反向电阻两种).人们利用这些不同特性构成各种具体的应用电路,分析不同电 ...

  5. MySQL实战 | 01 当执行一条 select 语句时,MySQL 到底做了啥?

    原文链接:当执行一条 select 语句时,MySQL 到底做了啥? 也许,你也跟我一样,在遇到数据库问题时,总时茫然失措,想重启解决问题,又怕导致数据丢失,更怕重启失败,影响业务. 就算重启成功了, ...

  6. python中mod是什么意思_【python中,mod_python到底做了些什么呢?】mod python 教程

    python 编程小白 ,不会用doctest 请大神指教怎么用!! >>> >>> def is_between(v, lower, higher): ...   ...

  7. 又被黑!百度到底做错了什么?

    前几天中国互联网巨头的市值又"更新"了一下,没想到百度现在"沦落"成了其它互联网公司市值的衡量单位. 图片来源自腾讯新闻 这一次,怕百度被"黑&quo ...

  8. 软件在安装时,到底做了些什么?

    软件在安装时,到底做了些什么? 大家每天都在用电脑,可能也经常在自己的电脑上安装软件.就算自己没安装过,至少也看到人家安装过软件.在这里,我不是想教你怎么安装软件,而是想向你展示,软件在安装的过程中, ...

  9. mysql add trandata_OGG add trandata 到底做了什么

    有的时候我们做OGG的时候add trandata会出现异常. 这里就剖析一下add trandata到底做了什么 GGSCI (yjfora81 as ggs_admin@testdb) 2> ...

最新文章

  1. DllImport dll中有些啥函数 及 dll中是否用到了别的dll
  2. ASP.NET中实现大结果集分页研讨 转
  3. Python2的Json反序列化工具
  4. 使用xdebug+wincachegrind的心得
  5. msg批量转html,SysTools MSG Converter(MSG格式转换器)
  6. dask 使用_在Google Cloud上使用Dask进行可扩展的机器学习
  7. REUSE_ALV_GRID_DISPLAY显示ALV,设置可编辑时,与内表数据同步问题
  8. 八.激光SLAM框架学习之LeGO-LOAM框架---框架介绍和运行演示
  9. gcc编译出现:error: dereferencing pointer to incomplete type
  10. hdu 1010 Tempter of the Bone(dfs+奇偶剪枝)
  11. three.js加载STL格式模型(vue中使用three.js52)
  12. voip和rtc_VOIP的发展进化史
  13. python中match方法_Python3.9.1中如何使用match方法?
  14. php计算器按钮功能,PHP实现的简单在线计算器功能示例
  15. 加班、加人、延期是糟糕的办法
  16. NOIP模拟赛 麻将
  17. 大力哥谈 DALI - DALI 电源调试和配置参数揭秘
  18. 【DONET学习笔记】C#与VB.NET除法运算的区别
  19. 如何下载网页中的图片
  20. python字典添加元素的2种方法_python中怎么向字典添加元素

热门文章

  1. 海康威视网络摄像头SDK二次开发(QT版本)
  2. uniapp项目创建打包生成安卓apk文件
  3. go test测试及命令
  4. Guitar Pro8手机电脑免费版吉他软件下载
  5. 卡诺模板_卡诺地图(K-地图)
  6. 中国十大帅哥总裁是谁啊?
  7. 如何打开联想计算机主机,联想计算机如何进入BIOS界面
  8. 关于springcloud使用shiro的权限控制
  9. 荣耀智慧屏鸿蒙当贝市场,如何用荣耀智慧屏Pro看电视直播?当贝市场陪你一起看!...
  10. 基于STM32C8T6、ESP8266-01S、JavaWeb、JSP、Html、JavaScript、Android、服务器和客户端设计、上位机和下位机设计等技术融合的物联网智能监控系统设计与实现