目录

  • 0 缘起
  • 1 free() 使用前
    • - free前程序做了什么
  • 2 free 的作用
    • - free对内存做了什么
    • - free对指针做了什么
  • 3 free后怎样做
  • 4 Q&A
    • (1) Q:有malloc 一定有free吗?
    • (2) Q:该free的地方没有free,会发生什么?
    • (3) 野指针和悬空指针?
  • 5 讲个故事
  • 6 回到开头的问题
  • 7 参考文献

0 缘起

在回顾用C语言实现链表的过程中,发现

  • 每个节点在开辟空间之后,到下一个节点被开辟空间之前,没有free();
  • 只有在删除节点时才用free()

上述两点让我产生疑惑,为什么节点都创建完了还不立即删除,而是在明确有删除节点的地方才进行free()?
所以决定对动态分配内存空间进行深入地理解。

1 free() 使用前

- free前程序做了什么

  • 在free前,程序一定进行了内存空间的动态分配。
  • malloc函数开辟指定大小的内存空间,并返回指向这段空间的起始地址的指针。
    (为叙述方便,这里用malloc()为例分配空间,返回的指针设为ptr.)
  • The behavior is undefined if the value of ptr does not equal a value returned earlier by malloc(), calloc(), realloc(), or aligned_alloc() (since C11).
    如果free的参数——指针,与具有相同变量名的,离它最近的内存分配函数所返回的指针所指向的地址不同,则可能会发生错误。
    ——在malloc()和free()之间,不能对其指针表示的地址进行修改。

2 free 的作用

- free对内存做了什么

  • Deallocates the space previously allocated by malloc(), calloc(),
    aligned_alloc, (since C11) or realloc(). [1]
    free释放了 由动态分配内存函数返回的指针 对应的内存空间
    注意:free释放的是内存空间,而不是指针。
    ——释放,指针指向的内存空间可以被其他变量所占用,
    但被占用前,内存空间中的内容仍然存在。但是无法判定是否被占用
  • The behavior is undefined if the memory area referred to by ptr has
    already been deallocated, that is, free() or realloc() has already
    been called with ptr as the argument and no calls to malloc(),
    calloc() or realloc() resulted in a pointer equal to ptr afterwards.[^1]
    同一内存空间对应的指针,在一次free后没有再次被分配空间的情况下,不能再次被free。

- free对指针做了什么

指针指向的地址,在没有重新分配内存前,也没有发生变化。

  • If ptr is a null pointer, the function does nothing.[^1]
  • free的参数——指针——为空时,free函数什么也不做

3 free后怎样做

free后,指针仍然指向分配的内存空间,指针指向的地址没有变化,地址内的内容也没有发生变化。变化的是这块内存的

  • The behavior is undefined if after free() returns, an access is made through the pointer ptr (unless another allocation function happened to result in a pointer value equal to ptr). [^1]
    在free后进行指针指向的地址访问——所谓的解引用(不是分配空间),可能出现错误。
  • 为了防止在释放内存空间后,紧接着访问内存空间带来的错误,需要在free后,将指针指向NULL
ptr=NULL;

ptr 指向地址为 0 的内存。NULL 其实就是 0x0。此处的地址,没有访问权限。
这就提醒别人不要对这个指针进行解引用的操作。这样一来,
指针ptr就与源来的分配空间不再关联。
而变量名为ptr的指针在此后可以再次通过动态分配内存指向新的内存空间。

#include<stdio.h>
int main(){int *x;x = (int*)malloc(sizeof(int)); *x = 3; printf("%d\n ", x); printf("%d\n", *x); free(x);if(x != NULL){printf("%d\n", x); printf("%d\n", *x); }x=NULL;printf("%d\n", x); printf("%d\n", *x); return 0;
}
最后运行输出的结果是
29540368
3
29540368
0
0
Segmentation fault (core dumpe

解释:
通过指针释放了动态分配的内存之后,指针还是指向原来的地址,
还可以访问原来的地址(不过原来的地址中的值可能变了),

而最后将指针置为 NULL 之后,显然指针不再指向原来的地址,
而且如果这时候再想通过指针访问对应的内存,就会报段错误。[^2]

4 Q&A

(1) Q:有malloc 一定有free吗?

A:是的
但并不是说一个malloc一定要对应一个free.要看具体的场景。
一旦free,就丧失了指针对这段内存空间的占有权和使用权。
比如物理结构是链表的实现场景,链表中的各个节点存储在当时分配的内存空间中。如果在构造链表的过程中,边申请存储节点的空间边释放节点空间,那么已经建好的结点的内容有可能被抹掉,所以只要有对该链表及其元素的操作,就不能free。

(2) Q:该free的地方没有free,会发生什么?

首先,什么时候该free?ptr对应的内存空间不再需要被访问或者被修改,那么,必须free.
否则,ptr对应的内存空间将不能被其他变量使用,造成内存泄漏(Memory Leak)

(3) 野指针和悬空指针?

野指针(wild pointer)
a pointer that has not been correctly initialized and therefore points to some random piece of memory. It is a serious error to have wild pointers.[3]
只是定义了指针指向的类型,而指针没有指向内存空间。把这样的指针叫野指针。

悬空指针(dangling pointer)
If a pointer still references the original memory after it has been freed, it is called a dangling pointer.
There is nothing wrong with having a dangling pointer unless you try to access the memory location pointed at by that pointer.[3]
若两个指针(p1和p2)指向同一块内存区域, 那么free(p1)后,p1和p2都成为悬空指针。
如果进一步将p1设置为NULL, 那么p2还是悬空指针。
使用 *p1 会导致非法内存访问(NULL对应的内存不允许程序访问),但是使用*p2却会出现无法预料的结果(可能是没有释放时该位置的原始指,也可能是其他值) [3]

悬空指针的处理——智能指针()待补充
基本思路:在释放一块内存时,将指向这块内存的指针变量设置为NULL。
访问指针变量前,先判断是否为NULL。

进阶:当有多个指针变量都指向同一块内存,释放这块内存时,需要将所有指针变量的值都置为NULL,这需要维护所有指向这块内存的指针变量的信息,
但是这种方式开销大,所以通常很少使用。
可以使用引用计数,只有当引用计数为0时,才释放内存,否则,只是引用计数减1.——引用计数法:如果一个对象没有任何引用与之关联,则说明该对象基本不太可能在其他地方被使用到,那么这个对象就成为可被回收的对象了。这种方式成为引用计数法。

5 讲个故事

小明租住了西虹市A小区302房,他与房东签了6个月的租房合同,签完合同小明得到了房间的钥匙。这六个月内小明就有了302房间的占有权和使用权,他可以添置家具,邀请客人,但不能对房间搞破坏,也不能修改门牌号。
六个月过去了,小明不再租住这个房子,由于时间仓促,他没来得及把钥匙交回给房东。
302可能此后没有人来租住,房东也比较懒,没有对房内摆设进行改动。也可能改动了。但这跟小明都没有关系了。
此后,

  • 房东可能换了把新锁,
  • 也可能没换,
  • 过几年A小区可能拆迁了。

那有一天小明喝醉酒,鬼使神差地,小明带着这把钥匙再去西虹市A小区302,对用以上的三种情况,分别会以下三种情况:

  • 钥匙打不开302的门
  • 钥匙打开了门,但门上的监控触发报警,因为私闯民宅是犯法的。
  • 他找不到A小区302了,因为A小区已经不存在了。

这个故事里,钥匙和302房价的空间分别代表什么呢?

6 回到开头的问题

为什么开辟了节点空间,也赋了值,但是不立马回收空间呢?
因为整个过程是在使用链表,而为节点开辟空间、赋值,是构造链表的过程。如果刚创建完节点,就立马free,节点就被摧毁了,那开辟空间,赋值也没了意义,链表也没法创建了。
所以,确定何时对指针指向的内存空间进行回收,是使用内存空间分配时,必须考虑的。
同时,手动进行内存空间分配,使得c语言更加偏向底层。为使用者带来了更加灵活自由的内存操作权利。当然,也带来了更大的不确定性。

7 参考文献

[1] 链接: free函数.
[2] 链接: 内存的分配与释放,内存泄漏.
[3] 链接: 野(wild)指针与悬空(dangling)指针.

c语言的free函数与内存空间释放相关推荐

  1. c语言分配多一个字符空间,关于C语言动态给字符串分配内存空间问题

    在动态分配的空间中如何输入字符串,关于C语言动态给字符串分配内存空间的问题相信很多朋友都不太了解,下面维维带来相关解答,赶紧看看吧. 用malloc来分配内存空间. 即输入几个字节的字符 系统就自动帮 ...

  2. 关于C语言的malloc函数以及内存泄漏的问题

    malloc函数 malloc函数的原型: (void *)malloc(int size) malloc函数的返回值是一个void类型的指针,参数为int类型的数据,即申请分配的内存大小,单位是字节 ...

  3. c语言动态与静态分配内存空间的区别

    所谓动态内存分配就是指在程序执行的过程中动态地分配或者回收存储空间的分配内存的方法.动态内存分配不象数组等静态内存分配方法那样需要预先分配存储空间,而是由系统根据程序的需要即时分配,且分配的大小就是程 ...

  4. 【C语言】free函数如何知道要释放多大空间

    一.malloc函数 C 库中有个函数 void *malloc(size_t size) ,该函数作用为分配所需的内存空间,并返回一个指向它的指针. 参数: size -- 内存块的大小,以字节为单 ...

  5. C语言 | 变量、函数及内存分区

    目录 全局变量(存储在数据区) 静态变量(存储在数据区) 全局变量.局部变量.静态全局变量.静态局部变量对比 二.函数 静态函数 三.内存分区 四.内存相关函数 malloc()  [#include ...

  6. vector利用swap()函数进行内存的释放

    首先,vector与deque不同,其内存占用空间只会增长,不会减小.比如你首先分配了10,000个字节,然后erase掉后面9,999个,则虽然有效元素只有一个,但是内存占用仍为10,000个.所有 ...

  7. c语言回收字符串空间,C语言基础知识(字符串,函数,内存空间)

    C 语言重点 arc4random() //产生一个随机数arc4random()A 随即数对41取余 得到0-40的数余数是正数 arc4random() % 11 + 20// 20 -30的数公 ...

  8. c语言指针跨函数使用内存

    #include <stdio.h> #include <malloc.h>//动态内存跨函数使用 void f(int ** q) {int j = 20;printf(&q ...

  9. C语言——动态开辟内存空间的函数

    目录 为什么需要动态开辟内存空间? 1.malloc函数 2.free函数 3.calloc函数 4.realloc 为什么需要动态开辟内存空间? 我们已经熟悉了基本的内存开辟方法: int a = ...

最新文章

  1. 利用python进行数据分析学习笔记(2)
  2. 基于 abp vNext 和 .NET Core 开发博客项目 - 博客接口实战篇(三)
  3. WebBrowser加载完毕后再往下执行
  4. osgEarth用户手册
  5. poj-2955-Brackets-区间DP
  6. html span离div块有边距,html块 div span
  7. 浏览器同源策略,及跨域解决方案
  8. 龙将加速浏览器_《使命召唤16》及战区迎来万圣节限时活动,迅游加速器助力流畅体验 18183手机游戏网...
  9. Visual Studio Code 调试 React Native (RN) 步骤 Mac版
  10. 关于EOS主节点竞选
  11. 【毕业设计】基于stm32的示波器设计与实现 - 单片机 物联网
  12. 零基础学python_03_字符串(拼接+换行+制表符)
  13. 51单片机电机测速程序c语言,单片机电机测速程序
  14. Hystrix php,详解 hystrix-go 使用与原理
  15. 笔记本电脑连接wifi显示无网络访问权限怎么办?
  16. 56个JavaScript 实用工具函数助你提升开发效率!
  17. Status of node rabbit@xxxxx... Error: unable to perform an operation on node ‘rabbit@xxxx
  18. DL/T645-1997通信规约解读
  19. Csdn修改账户手机绑定问题
  20. 基于 CNT 的射频辐射热计开发研究的 CPX-VF 低温探针台

热门文章

  1. 路由器固件模拟环境搭建(超详细)
  2. 今天给“小白”换上了新的风扇:酷冷至尊ICT-D725R!
  3. 零基础java自学流程-Java语言高级432
  4. Jmeter启动报错returned error code 5,解决方法
  5. 学生信息管理系统——JAVA 语言版(主页面+增+删+改+查+退)
  6. Bugku-CTF:学会如来神掌应该就能打败他了吧
  7. jmeter接口测试-接口文档信息不完善怎么做接口测试(一)
  8. 机器学习原来这么有趣!第四章:用深度学习识别人脸
  9. CSS笔记08-字体
  10. 工作伦理和消费美学的陷阱