动态内存管理


前言

在之前的学习中我们已经学习掌握了了代码区常量区、全局变量以及栈区,接下来我们学习动态内存管理,其主要是与堆区相关
在这里插入图片描述

一、为什么存在动态内存分配

如果我们想要定义一个很大的数组时,这时栈内无法满足我们的要求,栈内空间太小了。而 空间开辟大小是固定的。数组在申明的时候,必须指定数组的长度,它所需要的内存在编译时分配。但是对于空间的需求,不仅仅是该的情况。有时候我们需要的空间大小在程序运行的时候才能知道,那数组的编译时开辟空间的方式就不能满足了。 这时候就只能试试动态存开辟了。
在这里插入图片描述
所以进行动态内存管理
①可以申请大块内存,进行较为大类型的应用
②可以在程序运行期间进行申请,可以更灵活的使用内存空间

二、动态内存函数的介绍

1.malloc和free

malloc是一个动态内存开辟空间的函数,申请堆空间,但是不做任何初始化
这个函数向内存申请一块连续可用的空间,并返回指向这块空间的指针

void* malloc (size_t size) ; 

1.其中size_t size表示无符号整数申请几个字节。申请成功,malloc返回值void为一段连续空间的起始地址(最小字节对应的地址);申请失败,返回值为空。
2.返回值的类型是 void
,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定。
3,如果参数 size 为0,malloc的行为是标准是未定义的,取决于编译器。

另外一个函数free,专门是用来做动态内存的释放和回收的,函数原型如下:

void free (void* ptr);

1.free函数用来释放动态开辟的内存。
2.如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的。
3.如果参数 ptr 是NULL指针,则函数什么事都不做

malloc和free都声明在 stdlib.h 头文件中。 举个例子:
在这里插入图片描述
malloc、free是函数,必须时程序运行起来才能调用。编译的过程早就已经过了(在程序运行期间进行申请)

常见细节:

1.整体申请,整体释放

2.只申请内存不归还,会造成内存泄露。一种严重的问题,可用内存越老越少。进程退出了,内存泄露问题就不在了。

3.申请有大小,free没有告诉我们应该释放多少字节,那么free如何知道要释放多少字节?

目前free参数只能知道从哪开始释放。申请的时候,实际申请的空间会比你要的空间大一些,大出来的部分,用来保存本次申请的“元信息”(元信息:属性信息,对应堆空间的大小(也称为:内存cookie信息))

4.堆空间比较适合大块内存申请?还是小块内存申请?
大块内存申请

5.free究竟做了什么?
首先free前和后地址相同,但是free之后指针不可用
free用来取消内部的地址和堆空间的关系,所以没有关系无法使用
在这里插入图片描述

2.calloc

calloc 函数也用来动态内存分配。原型如下:

void * calloc (size_t num, size_of size);

size_t num元素个数 size_of size元素个数大小

函数的功能是为 num 个大小为 size 的元素开辟一块空间,并且把空间的每个字节初始化为0。并且也需要free函数释放空间
与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0。

#include <stdio.h>
#include <stdlib.h>
int main()
{
 int *p = calloc(10, sizeof(int));
 if(NULL != p)
 {
    //使用空间
    }
 free(p);
 p = NULL;
 return 0;
}

在这里插入图片描述

在这里插入图片描述

3.realloc

对已经分配的堆空间再次或多次进行调整,让动态内存管理更加灵活
有时候我们发现过去申请的空间太小了或申请的空间过大了,那么为了合理的时候内存,我们一定会对内存的大小做灵活的调整。因此 realloc 函数就可以做到对动态开辟内存大小的调整。

void* realloc (void* ptr, size_t size);

其中:
1.ptr 是要调整的内存地址(要调整的堆空间起始地址)
2.size 调整之后新的大小
3.返回值为调整之后的新的内存起始位置。
4.这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间。

realloc在调整内存空间存在两种情况:
①:原有空间之后有足够大的空间况
②:原有空间之后没有足够大的空间(可以扩展但是不够/不可以扩展)

对空间必须是连续的内存空间,因为存在对其进行遍历

对于①向后扩展空间,堆空间起始地址不变
对于②先跳过占用的空间找到开辟合适的空间大小,将原有内容拷贝过来再填写后面内容,最后将原先开辟的堆空间释放,对空间起始地址改变
在这里插入图片描述
在这里插入图片描述

如果调整空间依然不够,那么调整失败,此时返回值为NULL
在这里插入图片描述
以上3种堆空间申请方式都用free函数来释放

三、常见的动态内存错误

四、几个经典的笔试题

五、C/C++程序的内存开辟

六、柔性数组

1.柔性数组的特点

2.柔性数组的使用

3.柔性数组的优势


总结

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值