当前位置:首页 > 话题广场 > 攻略专题 > 游戏问答

C语言中动态内存是如何分配的?

该账户是华为云开发者社区的官方运营账户,提供对云计算的全面、深入的前景分析、丰富的技术干货、程序样本、华为云前沿信息共享。

本文由华为云社区《【云驻共创】C语言中动态内存分配的本质》,作者:G-washington分享。

C语言是一门面向过程的、抽象化的通用程序设计语言,广泛应用于底层开发。尽管C语言提供了许多低级处理的功能,但仍然保持着跨平台的特性,因为C语言具有可移植性,可拓展性,可重用性等特性,促使C语言仍然在编程语言排行榜上占据一定有利地位。而C语言中比较重要的就是指针,它可以用来链表操作,谈到链表,很多时候为此分配内存采用动态分配而不是静态分配。

内存分配的概念

通常定义变量(或对象),编译器在编译时都可以根据该变量(或对象)的类型知道所需内存空间的大小,从而系统在适当的时候为他们分配确定的存储空间。这种内存分配称为静态存储分配;有些操作对象只在程序运行时才能确定,这样编译时就无法为他们预定存储空间,只能在程序运行时,系统根据运行时的要求进行内存分配,这种方法称为动态存储分配。所有动态存储分配都在堆区中进行。

内存不是取之不尽用之不竭,4g、8g、16g是常见的电脑内存大小,打开任务管理器,能看到不同的应用占据的内存情况。如果一个应用程序占了大部分内存,估计别的应用就资源紧张了,那这个应用可能会被卸载,找个节省内存的。

内存管理是计算机接近物理本质的操作,那些程序语言之下的动作,最终都要调动内存来实现。系统的资源不是无限的,系统上运行的程序也不是只有这一个,忽略内存,就会设计出危险的、冗余的代码产品,或者没法更好的交互。

动态内存分配的特点

动态内存是相对静态内存而言的。所谓动态和静态就是指内存的分配方式。动态内存是指在堆上分配的内存,而静态内存是指在栈上分配的内存。动态内存分配的本质就是,什么时候需要一块内存的时候,再分配这块内存;当不再需要某一块内存的时候,就可以把这块内存释放掉。这种灵活的内存分配方式,正好适合链表这种数据结构。

传统数组的缺点

数组与动态内存分配相比有以下缺点:

  • 数组的长度必须事先指定,而且只能是常量,不能是变量。
  • 因为数组长度只能是常量,所以它的长度不能在函数运行的过程当中动态地扩充和缩小。
  • 对于数组所占内存空间程序员无法手动编程释放,只能在函数运行结束后由系统自动释放,所以在一个函数中定义的数组只能在该函数运行期间被其他函数使用。

而“传统数组”的问题,实际上就是静态内存的问题。但是动态内存就不存在这个问题,因为动态内存是由程序员手动编程释的,所以想什么时候释放就什么时候释放。只要程序员不手动编程释放,就算函数运行结束,动态分配的内存空间也不会被释放,其他函数仍可继续使用它。除非是整个程序运行结束,这时系统为该程序分配的所有内存空间都会被释放。

动态内存的申请与释放

动态内存的申请与释放主要依靠两个函数malloc和free。malloc 是一个系统函数,它是 memoryallocate 的缩写。其中memory是“内存”的意思,allocate是“分配”的意思。顾名思义 malloc 函数的功能就是“分配内存”,要调用它必须要包含头文件<;。

malloc()函数会向堆中申请一片连续的可用内存空间;若申请成功 ,,返回指向这片内存空间的指针 ,若失败 ,则会返回NULL, 所以我们在用malloc()函数开辟动态内存之后, 一定要判断函数返回值是否为NULL;返回值的类型为void*型, malloc()函数并不知道连续开辟的size个字节是存储什么类型数据的 ,所以需要我们自行决定 ,方法是在malloc()前加强制转 ,转化成我们所需类型 ,如: (int*)malloc(sizeof(int)*n).

下面使用 malloc 函数写一个程序,程序的功能是:调用被调函数,将主调函数中动态分配的内存中的数据放大 10 倍。

输出结果是:*p = 100

free是释放函数,在堆中申请的内存空间不会像在栈中存储的局部变量一样 ,函数调用完会自动释放内存 , 如果我们不手动释放, 直到程序运行结束才会释放, 这样就可能会造成内存泄漏, 即堆中这片内存中的数据已经不再使用, 但它一直占着这片空间, 所以当我们申请的动态内存不再使用时 ,一定要及时释放 .不过需要注意的是,释放并不是指清空内存空间,而是指将该内存空间标记为“可用”状态,使操作系统在分配内存时可以将它重新分配给其他变量使用。

那么,当指针变量被释放后,它所指向的内存空间中的数据会怎样呢?free 的标准行为只是表示这块内存可以被再分配,至于它里面的数据是否被清空并没有强制要求。不同的编译器处理的方式可能不一样。我们就看一下 VC++6.0 这个编译器是怎么处理的:

可见在 VC++6.0 中,当指针变量被释放后,虽然它仍然是指向那个内存空间的,但那个内存空间中的值将会被重新置一个非常小的负数。动态创建的内存如果不用了必须要释放。注意,一个动态内存只能释放一次。如果释放多次程序就会崩溃,因为已经释放了,不能再释放第二次。

综上所述,malloc 和 free 一定要成对存在,一一对应。有 malloc 就一定要有 free,有几个 malloc 就要有几个 free,与此同时,每释放一个指向动态内存的指针变量后要立刻把它指向 NULL。

注意事项

1)释放一块内存的一部分是不允许的。动态分配的内存必须整块一起释放。但是,realloc函数可以缩小一块动态分配的内存,有效地释放它尾部的部分内存。

2)不要访问已经被free函数释放了的内存。假定对一个指向动态分配的内存的指针进行了复制,而且这个指针的几份拷贝分散于程序各处。你无法保证当你使用其中一个指针时它所指向的内存是不是已被另一个指针释放。还要确保程序中所有使用这块内存的地方在这块内存释放之前停止对它的使用。

3)当动态分配的内存不再需要使用时,应该被释放,这样可以被重新分配使用。分配内存但在使用完毕后不释放将引起内存泄漏(memory leak)。

点击关注,第一时间了解华为云新鲜技术~华为云博客_大数据博客_AI博客_云计算博客_开发者中心-华为云

1.《C语言中动态内存是如何分配的?》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。

2.《C语言中动态内存是如何分配的?》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。

3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/gl/2177336.html

上一篇

12582农信通如何发信息?终于找到答案了农民朋友注意了,几招教你卖粮不受骗

下一篇

10085是什么电话?我来告诉你答案10086是中国移动客服,那10085、10087呢?

关于10内存如何分配,你需要知道这些Go 切片内存分配

关于10内存如何分配,你需要知道这些Go 切片内存分配

10内存如何分配相关介绍,切片是数组的抽象。 切片使用数组作为底层结构。 切片包含三个组件:容量,长度和指向底层数组的指针。 达到当天最大量API KEY 超过次数限制 通过使用 append 或 copy 函数可以增加切片的...

10内存如何分配看这里!C++ 内存管理学习笔记

10内存如何分配看这里!C++ 内存管理学习笔记

10内存如何分配相关介绍,需要更多C/C学习资料的小伙伴可以点击[跳转中]。欢迎加入~1。4种内存分配和版本 编程时,可以通过上图中的多种方法直接或间接操作内存。 下面将介绍四种C++内存操作方法: 对于GNU C:四种分配与...

10内存如何分配看这里!Go 切片内存分配

10内存如何分配看这里!Go 切片内存分配

10内存如何分配相关介绍,切片是数组的抽象。 切片使用数组作为底层结构。 切片包含三个组件:容量,长度和指向底层数组的指针。 达到当天最大量API KEY 超过次数限制 通过使用 append 或 copy 函数可以增加切片的...

10内存如何分配?总结很全面速看!Go 切片内存分配

10内存如何分配?总结很全面速看!Go 切片内存分配

10内存如何分配相关介绍,切片是数组的抽象。切片使用数组作为基本结构。片包含三个组件:容量、长度和指向基本数组的指针。 通过使用 append 或 copy 函数可以增加切片的容量。 append 函数可以为数组的末尾增加值,...

关于10内存如何分配,你需要知道这些C++ 内存管理学习笔记

关于10内存如何分配,你需要知道这些C++ 内存管理学习笔记

10内存如何分配相关介绍,需要更多C/C学习资料的小伙伴可以点击[跳转中]。欢迎加入~1。4种内存分配和版本 编程时,可以通过上图中的多种方法直接或间接操作内存。 下面将介绍四种C++内存操作方法: 对于GNU C:四种分配与...

10内存如何分配?我来告诉你答案开学攒机不求人,精选10400+RTX3060装机配置爽玩四年

10内存如何分配?我来告诉你答案开学攒机不求人,精选10400+RTX3060装机配置爽玩四年

10内存如何分配相关介绍,另外,到了一年开学季节,对于很多大学生朋友来说,安装既能高效完成学习任务,又能玩主流游戏大作的主机,可以说是一件出类拔萃的事情。(莎士比亚)。 但是,在这个特殊时期又不想花太多冤枉钱,怎样才能在预算内...

10内存如何分配?我来告诉你答案Go 切片内存分配

10内存如何分配?我来告诉你答案Go 切片内存分配

10内存如何分配相关介绍,切片是数组的抽象。切片使用数组作为基本结构。片包含三个组件:容量、长度和指向基本数组的指针。 通过使用 append 或 copy 函数可以增加切片的容量。 append 函数可以为数组的末尾增加值,...

10内存如何分配?终于找到答案了Go 切片内存分配

10内存如何分配?终于找到答案了Go 切片内存分配

10内存如何分配相关介绍,切片是数组的抽象。切片使用数组作为基本结构。片包含三个组件:容量、长度和指向基本数组的指针。 通过使用 append 或 copy 函数可以增加切片的容量。 append 函数可以为数组的末尾增加值,...