动态内存管理详解

server/2024/11/24 2:30:02/

1.malloc和free函数

2.calloc和realloc函数

3.动态内存管理的常见错误

(1)对空指针的解引用操作

(2)对动态开辟空间的越界访问

(3)对非动态开辟内存使用free

(4)使用free释放动态内存空间的一部分

(5)对于同一块动态内存的多次释放

(6)动态开辟内存忘记释放

4.几道关于动态内存管理的经典例题

5.柔性数组

6.C语言里的内存区域划分(附录)


一.malloc和free函数

1.引入:为什么要有动态内存管理

我们已经掌握了两种内存开辟的方式:

但是上述的开辟空间的⽅式有两个特点:

• 空间开辟⼤⼩是固定的。

• 数组在申明的时候,必须指定数组的⻓度,数组空间⼀旦确定了⼤⼩不能调整

但是对于空间的需求,不仅仅是上述的情况。有时候我们需要的空间⼤⼩在程序运⾏的时候才能知 道,那数组的编译时开辟空间的⽅式就不能满⾜了。 C语⾔引⼊了动态内存开辟,让程序员⾃⼰可以申请和释放空间,就⽐较灵活了

2.malloc函数:

(1)函数原型:

这个函数向内存申请一块连续可用的空间,并返回指向这块空间的指针

注意:

1.这个函数就是用来开辟空间的,且单位为“字节

2.若开辟成功,就返回一个指向该空间的指针

(开辟成功返回的指针类型为void*,所以我们要使用的话得先将其强制转换

3.若开辟失败,返回空指针,且返回的空指针NULL无法被使用

4.使用该函数以及后续一系列的free,realloc,calloc都需要包含头文件<stdilb.h>

5.如果size参数为0,malloc的行为标准是未定义的,取决于编译器

(2)使用函数:

3.free函数:

(1)函数原型:

这个函数顾名思义就是来释放动态内存的

注意:

1.如果参数ptr指向空指针,那么free什么事都不用做

2.如果参数ptr指向的空间不是动态内存,那么free的函数的行为是未定义的

3.mclloc函数在申请内存之后一定要释放内存,否则会导致内存泄漏,或者因为重复开辟内存导致占用大量内存空间

(2)函数使用:


二.calloc和realloc函数

1.calloc函数:

(1)函数原型

注意:

1.它可以为num个占用size个字节的元素开辟空间

2.和malloc区别就在于,calloc会把申请的空间全部初始化为0

(2)使用

所以如果我们对申请的内存要求初始化时,就可以很方便地使用calloc函数

2.realloc函数:

(1)函数原型

注意:

1.realloc作为动态内存调整函数,它的出现可以动态内存管理更加灵活

2.ptr表示要调整的内存地址

3.size表示调整后新内存的大小,单位为字节

4.返回值为调整后内存的起始地址

5.这个函数在调整原空间内存的大小的基础上,还会将原来的数据移动到新的内存中

6.realloc调整空间存在以下两种情况:

(1)原空间后足够大空间

(2)原空间后没有足够大空间

(2)使用

当发生情况1时,要扩展内存直接就在原有空间后追加

当发生情况2时,当原有空间之后没有足够空间时,realloc就会在堆空间上重新找一块空间来存放,这样函数返回的就是一个全新的地址


三.动态内存管理的常见错误

1.对空指针(NULL)的解引用操作:

2.对动态开辟空间的越界访问:

3.对非动态开辟的内存使用free:

4.使⽤free释放⼀块动态开辟内存的⼀部分:

5.对于同一块动态内存的多次释放:

6.动态开辟内存忘记释放(内存泄漏):

切记:动态开辟的内存一定要手动释放,否则会内存泄漏!!!!!


四.几道关于动态内存管理的经典例题

1.题目一:

这串代码运行起来系统会崩溃:因为在过程中GetMemory传的是str本身,也就是一个空指针(但GetMemory确实开辟了一块空间),GetMemory函数并没有改变str指向一个空指针,而是在这个空指针后面又开辟了一块空间(但如果GetMemory返回p,再让str去接收的话也可以实现对程序的完善(这也是更为简单的一种方法)),因此在下面的strcpy中,因为要拷贝字符串,就必然意味着对str这个地址的解引用,二此时str指向的是空指针,也就意味着对空指针进行解引用,而这个操作本身就会导致代码的瘫痪,因此我们若是想要改进代码,使其真正打印hello world,就意味着GetMemory在传参时必须传的时空指针的指针,也就是*str(空指针)的指针,也就是**p,同时,下面的一行代码也应该从空指针改为空指针的指针。

(解释很长,但很高兴能看到你认真读完)

因此改进方式如下:

2.题目二:

这串代码运行出来会是一串乱码,如下:

因为这里p作为一个临时变量,p的生命周期仅仅在GetMemory中,当调用函数后,p指向的栈空间也被返还给操作系统,此时str接受到的返回值也就是一个野指针,也就是这题的主要问题所在,但值得注意的是,虽然p的空间被返还了但str仍旧有可能找到p的地址(在p原所占的空间没来得及被操作系统分配给其他地方时),因此这里打印出乱码也是一个可能情况。

3.题目三:

这个题目就相对比较好处理些,主要应该考虑到的就是这里缺失free释放空间而造成的内存泄漏。

4.题目四:

这里打印出的结果就仅仅是一个“world”,而且还产生了非法访问的问题,具体原因如下:第一点,当代码在执行到free后并没有将str置为空指针NULL,这也就导致了虽然str所指向的空间被释放了,但str仍旧可以找到那一块区域的地址,相应的,str也成为了存着“hello”这个字符串的野指针,当他再一次进入if循环并且通过strcpy打印world时,指向的是hello里h的地址,自然也就使world覆盖了原来的hello,虽然代码可以打印出结果,但代码运行过程中很明显地出现了非法访问与野指针的问题,这也就是这题所考的内容。


五.柔性数组

1.柔性数组的概念:

C99中,结构中的最后⼀个元素允许是未知⼤⼩的数组,这就叫做『柔性数组』成员

2.柔性数组的特点:

举例:

3.柔性数组的使用:

这样柔性数组成员a,相当于获得了100个整型元素的连续空间。

4.柔性数组的优点:

相较于上述方法,还有一种方式同样可以实现:

这两种方式比较过后:


六.C语言里的内存区域划分(附录)

ok,这次的分享就到这,下播。


http://www.ppmy.cn/server/144419.html

相关文章

无监督跨域目标检测的语义一致性知识转移

Semantic consistency knowledge transfer for unsupervised cross domain object detection 无监督跨域目标检测的语义一致性知识转移 作者: Zichong Chen, Ziying Xia, Xiaochen Li, Junhao Shi, Nyima Tashi, Jian Cheng 所属机构: 电子科技大学信息与通信工程学院&…

MySQL中索引全详解

第一部分&#xff1a;什么是索引 索引在数据库中就像书的目录&#xff0c;能够快速定位数据位置&#xff0c;从而提升查询效率。没有索引时&#xff0c;数据库查询需要从头到尾扫描整个表&#xff08;称为全表扫描&#xff09;&#xff0c;这在数据量大时非常耗时。有了索引后&…

如何优化Sql的查询性能?

使用适当的索引 原理:索引是数据库中的一种数据结构,可以加快数据的检索速度。 性能提升: 大大减少了数据库需要扫描的数据量可以避免全表扫描,直接定位到所需数据在排序和分组操作中也能显著提高效率 优化查询语句 原理:精简和优化SQL语句可以减少数据库的工作量。 性能提升: …

Python 之网络爬虫

一.认识HTML 1.什么是HTML &#xff08;HyperText Markup Language&#xff09; HTML是超文本标记语言的缩写&#xff0c;它包含一系列的标签&#xff0c; “超文本”是一种组织信息的方式&#xff0c;利用HTML标记&#xff0c;告诉浏览器被标记的内容如何显示到浏览器页面上…

CSS布局学习1

vertical-align: 元素所在一行垂直方向的对齐&#xff0c;谁小的谁动&#xff01;父元素中的子元素&#xff0c;只能控制行内元素&#xff01;&#xff01;&#xff01;用在单元格内可以用来春之对齐。 text-aligh&#xff1a;文字对齐&#xff0c;left, right, center img图…

《现代制造技术与装备》是什么级别的期刊?是正规期刊吗?能评职称吗?

​问题解答 问&#xff1a;《现代制造技术与装备》是不是核心期刊&#xff1f; 答&#xff1a;不是&#xff0c;是知网收录的第二批认定学术期刊。 问&#xff1a;《现代制造技术与装备》级别&#xff1f; 答&#xff1a;省级。主管单位&#xff1a;齐鲁工业大学&#xff0…

mysql复习

Mysql三种搜索引擎 Memory MEMORY是MySQL中一类特殊的存储引擎。它使用存储在内存中的内容来创建表&#xff0c;而且数据全部放在内存中。 底层使用hash和B-树 MyISAM 底层使用B树 采用表级锁来提供并发支持能力 执行读取操作的速度很快,而且不占用大量的内存和存储资源…

wpf中几种获取ComBox中值的方法

方法一&#xff1a; string test null;foreach (ComboBoxItem item in e.AddedItems){test item.Content.ToString();break;}方法二&#xff1a; ComboBoxItem cbi (ComboBoxItem)(sender as ComboBox).SelectedItem;string selectedText cbi.Content.ToString();方法三…