动态内存管理

简介: 动态内存管理

动态内存管理

大家好,我是晓星航。今天为大家带来的是动态内存分配相关知识点的讲解!😀

1. 为什么存在动态内存分配

int val = 20;//在栈空间上开辟四个字节

char arr[10] = {0};//在栈空间上开辟10个字节的连续空间

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

1.空间开辟大小是固定的。

2.数组在申明的时候,必须指定数组的长度,它所需要的内存在编译时分配。

但是对于空间的需求,不仅仅是上述的情况。有时候我们需要的空间大小在程序运行的时候才能知道,那数组的编译时开辟空间的方式就不能满足了。

这时候就只能试试动态存开辟了。

2. 动态内存函数的介绍

2.1 malloc和free

malloc - 动态内存分配(memory allocation)

头文件为:#include

参数有一个:开辟空间大小 单位是字节

返回值:开辟成功返回分配区域的起始地址,开辟失败返回NULL(空指针)

开辟成功则有开辟好了指定的空间

如果开辟失败则会返回空指针

free - 内存释放函数

头文件:#include

参数有一个:指针指向一个要释放内存的内存块

返回值:无

2.2 calloc - 开辟一块以0初始化的数组(没有malloc的效率高)

头文件:#include

参数有两个:1:元素的个数 2:每一个元素的大小

返回值:开辟空间的起始地址

2.3 realloc - 增容函数

功能:

1可以开辟空间

2也可以调整空间

头文件:#include

参数有两个:1:开辟空间的起始地址 2:增加到的容量大小(将原大小增加到某个大小)

返回值:返回重新调整之后开辟好空间的起始地址

情况一:直接在原有基础上跨大一倍,起始地址和变化后地址一样。

情况二:新开辟一个扩大一倍的新空间,将原有内容全部转移到我们新开辟的空间,返回新的起始地址。

情况三:realloc调整空间失败,返回NULL。

改正后版本:这种写法就很好的避免了函数返回空指针

3. 常见的动态内存错误

3.1 对NULL指针的解引用操作

空指针不能进行解引用操作

3.2 对动态开辟空间的越界访问

这里开辟了10个空间 但是却访问了11个空间 因此越界访问了

3.3 对非动态开辟内存使用free释放

补充:栈上的空间自动创建自动销毁。进入作用域自动创建,出作用域自动销毁。

3.4 使用free释放一块动态开辟内存的一部分

3.5 对同一块动态内存多次释放

3.6 动态开辟内存忘记释放(内存泄漏)

4. 几个经典的笔试题

4.1 题目1:

请问运行Test 函数会有什么样的结果?

1:str并没有开辟空间,还是空指针。

2:str还是NULL指针的时候,会非法访问内存 程序会崩溃

3:没有assert函数断言p是否为空指针

4:在使用完后没有用free将其释放掉

4.2 题目2:

请问运行Test 函数会有什么样的结果?

返回栈空间地址问题:

1:str是野指针

2:str用完未释放

3:str未置成NULL(空指针)

4.3 题目3:

请问运行Test 函数会有什么样的结果?

1:忘记释放内存

2:忘记将指针置为空

4.4 题目4:

请问运行Test 函数会有什么样的结果?

1:str内存释放之后,为将str置为空指针

2:因为之前对str指向的空间已经释放,不能再次使用!形成非法访问内存!

5. C/C++程序的内存开辟

C/C++程序内存分配的几个区域:

1.栈区(stack):在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。 栈区主要存放运行函数而分配的局部变量、函数参数、返回数据、返回地址等。

2.堆区(heap):一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。分配方式类似于链表。

3.数据段(静态区)(static)存放全局变量、静态数据。程序结束后由系统释放。

4.代码段:存放函数体(类成员函数和全局函数)的二进制代码。

6. 柔性数组

结构中的最后一个元素允许是未知大小的数组,这就叫做『柔性数组』成员。

6.1 柔性数组的特点:

特点:

1:结构中的柔性数组成员前面必须至少一个其他成员。

2:sizeof 返回的这种结构大小不包括柔性数组的内存。

3:包含柔性数组成员的结构用malloc ()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。

在用sizeof计算大小的时候,柔性数组的大小是不被算进去的

6.2 柔性数组的使用

这里struct S2大小本应该是4+n*4个字节的大小,但因为int arr[]是柔性数组,因此struct大小为4。

6.3 柔性数组的优势

第一个好处是:方便内存释放

如果我们的代码是在一个给别人用的函数中,你在里面做了二次内存分配,并把整个结构体返回给用户。用户调用free可以释放结构体,但是用户并不知道这个结构体内的成员也需要free,所以你不能指望用户来发现这个事。所以,如果我们把结构体的内存以及其成员要的内存一次性分配好了,并返回给用户一个结构体指针,用户做一次free就可以把所有的内存也给释放掉。

第二个好处是:这样有利于访问速度

连续的内存有益于提高访问速度,也有益于减少内存碎片。(其实,我个人觉得也没多高了,反正你跑不了要用做偏移量的加法来寻址)

注:内存碎片是指开辟的内存与相邻内存之间浪费的空间称之为内存碎片。

感谢各位读者的阅读,本文章有任何错误都可以在评论区发表你们的意见,我会对文章进行改正的。如果本文章对你有帮助请动一动你们敏捷的小手三连一波,你的每一次鼓励都是作者创作的动力哦!😘

目录
相关文章
|
3月前
|
程序员
动态内存管理
动态内存管理
20 0
|
8月前
|
编译器 程序员 C语言
动态内存管理(超详细!)
动态内存管理(超详细!)
68 2
|
8月前
|
程序员 C语言 C++
详解动态内存管理!
详解动态内存管理!
|
程序员 编译器 C语言
动态内存管理(2)
动态内存管理(2)
53 0
|
编译器
动态内存管理(1)
动态内存管理(1)
67 0
|
程序员 编译器 C语言
动态内存管理总结
动态内存管理总结
61 0
|
程序员 C语言 C++
动态内存管理-2
动态内存管理
58 0
|
编译器 文件存储 数据库
Day_17> 动态内存管理
Day_17> 动态内存管理
|
C语言
动态内存管理(上)
动态内存管理(上)
58 0

热门文章

最新文章