栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

动态内存二

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

动态内存二

动态内存管理

那么我们就要引用动态内存这个概念 ——动态内存(Dynamic Memory),使用户能够指定虚拟操作系统启动的RAM容量,并将平台可用的系统内存最大化。

申请动态内存是在堆区中申请,而堆区对于用户是要自己管理的。

我们这里介绍几个涉及动态内存的函数,这些函数都是在#include工具包中

malloc(),这个函数的作用是申请一块指定大小的连续的内存空间

传递的参数是void *(size_t size)

例如int *p=(int*)malloc(sizeof(int)*n)

这就在堆区中申请了n个int大小的内存空间

前面提到,堆区的内存是要求使用者自己管理的

在使用完之后还要进行释放操作,如果不进行释放,那么下一次要使用的时候就不能再次使用这一块地方

因此后面都要跟上free(p),意思是释放掉p指向的内存空间

同时要对p=NULL;这一步是为了防止多次free导致访问到了不允许访问的地址引起指针崩溃的情况。
memset(),这个函数的作用是未初始化的内存进行初始化,传入参数为(void *,int value,size_t size)

特别要注意的是,这里传入的size是字节数

例如

int *p=(int *)malloc(sizeof(int)*10);

memset(p,0,sizeof(int)*10);

那么这就为申请到的未初始化的内存进行了初始化。那么这里有一个问题,依据传入的参数,我们将内存初始化为全为0,那么可不可以是1呢

其实是不可以的

0,1分别在内存上按00000000和01010101存储的,那么对应的1存入内存中就不是1了。

calloc(),这个函数的作用是用来申请具有初始化的连续的内存空间,传入参数是(int value,size_t size)。

int *p=(int*)calloc(0,sizeof(int)*10);

这里就申请到了具有初始化的连续的内存空间

realloc(),这个函数的作用是对内存进行扩容操作,传入参数是(void *,size_t size)

例如

int*p=(int *)malloc(sizeof(int )*10);

int *q=(int*)realloc(p,sizeof(int)*15);

这就把p从10个int 扩容成了15个int

但是进行扩容操作,这就涉及到了几个问题

第一,后续内存空间足够,可以扩容

第二,堆内存不足,扩容失败

第三,后续堆内存不足,不能分配,那么关于这个情况,堆内存就会有新的解决方案,他会自己找一块足够大的新的地方,然后再将原来的值复制过去,就完成了扩容。

我们来观察以下代码中的错误

 示例1就是一个完整的malloc申请内存空间的过程

示例2有错误,是因为int *ip实际上是在栈当中操作内存,而free是对堆内存的操作,面对的对象不同,所以会有这样的问题

示例3在释放了申请的内存后再对原内存进行操作,实际上就是访问了不该访问的内存空间,会发生指针崩溃

示例4是访问了不允许访问的内存,会引发程序崩溃

示例5是用下标访问申请内存是,多访问了一个没这样也是访问到了不允许访问的内存

示例6是移动了指针的指向,会访问到不允许访问的内存

示例7如果要把在函数体内申请的堆内存拿到主程序中使用的话,我们应该要返回它,例如

这样就可以正确的访问到了

如果在函数体内定义一个局部变量,这个是不能返回的,因为在程序结束指针这个区域也就消失了,所以是不可以返回的

 

 

 这里的第一个就可以和示例7联系

而二三,也就是不能返回局部变量的问题。

参考:图论教育之动态内存管理

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1034322.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号