由free()函数引发的关于动态内存分配的思考

由free()函数引发的关于动态内存分配的思考

前几天力扣刷题时无意中看到的这道(伪)动态内存分配题激起了我对内存的好奇心,我之前做链表和二叉树的时候遇到过malloc()函数,但是当时只知道他是用来分配空间的,具体怎么分配还是一头雾水,出现的free()更是让我一时懵逼,不知道注释在说什么,于是有了下面这篇了解动态内存分配博客的诞生:

如图红框中的注释所示,

  • Note: The returned array must be malloced, assume caller calls free().
  • 注意:返回的数组必须被malloced,假设调用者调用free()。(源自谷歌翻译)

在这里插入图片描述

注释中出现的malloc()函数和free()函数属于系统提供的库函数,用来对内存进行动态分配,关于这一点不得不提到他们存储家族的四大金刚

  1. malloc(开辟动态存储区)

  2. calloc(开辟动态存储区)

  3. realloc(重新分配动态存储区)

  4. free(释放动态存储区)

    关于他们的详细功能我们先按下不表,如果你着急了解他们四个的介绍,可以拖动滑条至底部浏览详细介绍。接下来的部分我将由浅入深逐步分享我对这四个函数的分析过程


首先,我们需要了解内存是什么?

内存(Memory)是计算机的重要部件之一,也称内存储器和主存储器,它用于暂时存放CPU中的运算数据,与硬盘等外部存储器交换的数据。它是外存与CPU进行沟通的桥梁,计算机中所有程序的运行都在内存中进行,内存性能的强弱影响计算机整体发挥的水平。只要计算机开始运行,操作系统就会把需要运算的数据从内存调到CPU中进行运算,当运算完成,CPU将结果传送出来。(源自百度百科)

程序与程序之间是相互独立的,不通过特殊手段通常无法相互访问,程序所占的内存也是如此,相互独立的。比如你家的某视频播放器和某学习工具是互相独立互不影响的,内存通常不能相互访问。通过这我们不难发现,内存就是暂时存放外存和CPU数据的桥梁,他决定你可以多开几个程序,多运行几个app电脑不会卡顿,所以程序开多了卡顿你可以试着给电脑加内存条,尤其是电脑配了副屏之后加内存条更能凸显其重要性。
在这里插入图片描述


其次,C程序所占内存由哪四部分构成?

  1. 代码区(code area)

    ​ 包括只读存储区和文本区,其中只读存储区存储字符串常量,就是常量区,文本区存储程序的机器代码(二进制代码)。

  2. 全局区(Static area)

    1. 1 全局初始化区(DATA段)

      ​ 存储程序中已初始化的全局变量和静态变量

    ​ 2.2 未初始化段(BSS段)

    ​ 存储程序中未初始化的全局变量和静态变量

  3. 堆区(Heap)

    堆是一个大容器,它的容量要远远大于栈,但没有栈那样先进后出的顺序,一般由程序员分配释放, 若程序员不释放,程序结束时可能由操作系统回收 。

    注意:它与数据结构中的堆不同,分配方式类似于链表,在程序运行过程中可以动态增加堆大小(移动break指针),从低地址向高地址增长。

  4. 栈区(Stack)

    栈是一种先进后出的内存结构,一般由编译器在需要的时候分配,在不需要的时候自动清除的变量的存储区。里面的变量通常是函数的返回地址、参数、局部变量、返回值等,从高地址向低地址增长。其操作方式类似于数据结构中的栈。

    在这里插入图片描述
    没有对比就没有伤害,hhh
    在这里插入图片描述


然后,动态内存分配究竟是什么?

在c/c++语言中,编写程序有时不能确定数组应该定义为多大,因此这时在程序运行时要根据需要从系统中动态多地获得内存空间。所谓动态内存分配,就是指在程序执行的过程中动态地分配或者回收存储空间的分配内存的方法。动态内存分配不像数组等静态内存分配方法那样需要预先分配存储空间,而是由系统根据程序的需要即时分配,且分配的大小就是程序要求的大小。(源自百度百科)

在计算机科学中, 动态内存分配(Dynamic memory allocation)又称为堆内存分配,是指计算机程序在运行期中分配使用内存。它可以当成是一种分配有限内存资源所有权的方法。动态分配的内存在被程序员明确释放或被垃圾回收之前一直有效。与静态内存分配的区别在于没有一个固定的生存期。这样被分配的对象称之为有一个“动态生存期”。(源自维基百科)

以上两部分是国内外两大百科网站对这个名词的解释


最后,作为程序员的我们最重要的是知道这四个库函数究竟怎么用。

C语言动态内存分配函数必须在头文件 stdlib.h 中声明,当然你像我一样狗用万能头文件bits/stdc++.h我也无话可说

  1. malloc()函数

    其作用是在内存的动态存储区中分配一个长度为size的连续空间。

    用来在堆(Heap)中分配指定大小的内存,单位为字节(Byte),函数返回void *指针;

    malloc(100);        //开辟100字节的临时分配域,函数值为其第一个字节的地址。
    
  2. realloc()函数

    其作用是假如通过malloc()函数或malloc()函数获得了动态内存空间,想改变其大小,可以用realloc()函数重新分配

    realloc(p, 50);		//将p指向的已分配的动态空间改为50字节
    
  3. calloc()函数

    其作用是在内存的动态分配区中分配n个长度为size的连续空间,这个空间一般比较大,足以保存一个数组

    p=calloc(50, 4);    //开辟50×4个字节的临时分配域,把首地址赋给指针变量P
    
  4. free()函数

    其作用是释放指针变量P所指向的动态空间,使这一部分空间能重新被其他变量使用。

    free(p);			//释放指针变量p所指向的已分配的动态空间
    

    总结:

函数函数原型描述
mallocvoid * malloc(unsigned int size)分配指定数量的字节
reallocvoid * realloc(void * p, unsigned int size)调整指定内存块的大小,必要时会重新分配
callocvoid * calloc(unsigned n, unsigned size)分配指定数量的字节,并初始化为 0
freevoid free(void * p)释放指定的内存块

以上方法仅供参考,欢迎互联网的广大朋友们提出指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值