c语言动态内存分布

news2024/11/25 22:53:40

前言:

随着我们深入的学习c语言,之前使用的静态内存分配已经难以满足我们的实际需求。比如前面我们的通讯录功能的实现,如果只是静态内存分配,那么也就意味着程序开始的内存分配大小就是固定的,应该开多大的空间呢?开大了是浪费,开小了又不能满足自己的需求。而动态内存分配可以完美的解决这个问题,真正地做到需要多少空间就开多大的空间(根据需要动态地分配和释放内存空间).

总的来说,动态内存分配比静态内存分配更灵活,效率也更高,避免了空间的浪费。

下面就开始动态内存的学习吧。

1.动态内存函数:

1.malloc

2.free

3.calloc

4.realloc

这些函数都声明在stdlib头文件中。

1.1 malloc和free

malloc:

void* malloc (size_t size);

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

参数size表示需要开辟的空间字节大小,返回类型为void*,泛型指针,指向被开辟空间首元素地址。具体指向什么类型的数据需要使用者自己决定。

需要注意的是,如果开辟空间失败这个函数会返回NULL,所以为了避免使用空指针,在使用这个函数之后需要判断是否返回了NULL.

free:

void free (void* ptr);

free函数用来释放掉动态开辟的内存。

参数prt表示的是需要释放动态内存空间的指针。 

这个函数非常重要,因为如果动态内存分配的空间没有及时释放的话,可能会造成内存泄漏,而长时间运行的程序中存在内存泄漏会逐渐消耗系统的可用内存,最终可能导致程序崩溃或系统变得不稳定。

所以为了避免内存泄漏的情况发生,我们应该养成即使释放动态内存的习惯。

举例:

int main() {
	//使用malloc动态开辟空间的例子
	int num = 0;
	scanf("%d", &num);
	int* ptr = NULL;
	ptr = malloc(num * sizeof(int));//开辟了num个整数类型元素大小的空间,返回这片空间的起始位置给ptr
	if (ptr == NULL) { //判断是否申请空间成功
		perror("malloc");
	}
	//初始化申请空间的元素
	for (int i = 0; i < num; i++) {
		*(ptr + i) = i;
	}
	//释放空间,防止空间泄漏,指针置空,防止野指针
	free(ptr);
	ptr = NULL;
	
	return 0;
}

这里我输入的num=10.

监视:

我们发现ptr指针确实指向了10个整型大小的空间,能正常初始化。

释放空间后:

为什么要释放掉空间后将ptr置空?

这是因为虽然我们将动态开辟的空间释放掉了,但是ptr依旧指向这片空间,但是此时ptr已经没有权限操作这片空间了,所以我们需要置空。

1.2 calloc

void* calloc (size_t num, size_t size);

calloc函数与malloc函数相似,都是向内存申请一块连续可用的空间,并返回指向这块空间的指针,区别是,calloc申请的空间里的每个字节会默认初始化为0。

第一个参数num是元素的个数,size表示的是元素的字节大小,开辟num个大小为size的元素的空间,返回开辟空间的起始地址。

 其实malloc和calloc的用法也基本一致,只不过比malloc更加省事,不用担心初始化的问题。

举例:

int main() {
	int* p = (int*)calloc(10, sizeof(int));
	if (p == NULL) {
		perror("calloc");//打印错误信息
	}
	free(p);
	p = NULL;
	return 0;
}

监视指针p:

我们可以看到,在申请到空间后,空间里的元素都被初始化为了0.

1.3 realloc

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

realloc函数可以做到对动态开辟内存大小的调整,如果此时申请的动态空间不够,那么我们可以使用realloc函数来进行“扩容”。

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

 realloc申请空间会遇到两种情况:

1.原空间后面有足够空间,会直接在原来ptr指向空间后面追加,返回的地址也是ptr指向的地址。

2.原有空间后面空间不够,那就在堆空间另找一片空间,这个时候返回的的地址就会是一个随机值。

 举例:

int main()
{
    int* ptr = (int*)malloc(120);
    int ptr2 = ptr;//记录原来ptr指向的地址
    if (ptr == NULL)
    {
        perror("malloc");
    }
   
    //扩展容量
    ptr = (int*)realloc(ptr, 1000);
    if (ptr == NULL)//如果申请失败返回NULL
    {
        perror("realloc");
    }
    if (ptr == ptr2) {
        printf("情况1\n");
    }
    else {
        printf("情况2\n");
    }
    free(ptr);
    ptr = NULL;
    return 0;
}

我们看到,realloc申请的空间返回的地址不是原来的ptr指向的地址.

我们再来改一下代码:

int main()
{
    int* ptr = (int*)malloc(120);
    int ptr2 = ptr;
    if (ptr == NULL)
    {
        perror("malloc");
    }
   
    //扩展容量
    ptr = (int*)realloc(ptr, 140);//扩容的空间很小
    if (ptr == NULL)//如果申请失败返回NULL
    {
        perror("realloc");
    }
    if (ptr == ptr2) {
        printf("情况1\n");
    }
    else {
        printf("情况2\n");
    }
    free(ptr);
    ptr = NULL;
    return 0;
}

现在我们把realloc申请的空间改小一点,为了能找到符合情况1(realloc在原来ptr指向空间后面追加).

当然这也只是偶然情况,就算是扩容改小一点也不一定就会直接追加空间在ptr指向空间后面。

2.常见的动态内存错误

在介绍了几个动态内存函数的用法之后,我们再来看看在使用动态内存函数时经常犯的错误吧。

2.1 对NULL指针的解引用操作

void test()
{
 int *p = (int *)malloc(INT_MAX/4);
 *p = 20;//如果p的值是NULL,就会有问题
 free(p);
}

如果我们申请的空间太大就有可能开辟空间失败,这个时候指针p接收到的就是NULL,而对NULL解引用操作就会导致错误。

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

void test()
{
 int i = 0;
 int *p = (int *)malloc(10*sizeof(int));
 if(NULL == p)
 {
 exit(EXIT_FAILURE);
 }
 for(i=0; i<=10; i++)
 {
 *(p+i) = i;//当i是10的时候越界访问
 }
 free(p);
}

我们这里只是申请了10个整型元素大小的空间,这个时候*(p+10)其实已经越界访问了,此时程序就会出错。

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

void test()
{
 int a = 10;
 int *p = &a;
 free(p);//ok?
}

上面我们已经知道了free是用来释放动态内存的空间的,而如果对非动态开辟内存使用free释放,等待你的就是这个:

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

void test()
{
 int *p = (int *)malloc(100);
 p++;
 free(p);//p不再指向动态内存的起始位置
}

在执行malloc函数分配内存后,指针p指向动态内存的起始位置。然而,在将指针p增加1后,它不再指向分配的内存起始位置。因此,当在之后使用free函数来释放内存时,由于free函数要求传入指向malloc分配内存起始位置的指针,传入p将导致未定义的行为。这可能会导致程序崩溃或出现其他问题。

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

void test()
{
 int *p = (int *)malloc(100);
 free(p);
 free(p);//重复释放
}

重复释放同一内存块会导致未定义的行为,可能会导致程序崩溃或出现其他问题。 

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

void test()
{
 int *p = (int *)malloc(100);
 if(NULL != p)
 {
 *p = 20;
 }
}
int main()
{
 test();
 while(1);
}

内存泄漏指的是程序在执行期间申请了一定量的内存空间,但在使用完毕后没有及时释放,导致这部分内存空间永远无法被程序使用,从而浪费了宝贵的系统资源。所以我们一定要及时释放掉申请的空间,这样才能“有借有还再借不难”。

总结

学习动态内存是如何分配的可以让我们以后写出来的程序更加高效灵活,这也是我们作为程序员的基本素养,同时,我们也应该注意正确使用动态内存分配,避免一些常见的错误。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1070906.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

重启Oracle数据库命令列表逐步操作

&#x1f495;欢迎来到 Oracle 数据库重启教程&#x1f495; &#x1f3af;第一步&#xff1a;以 oracle 身份登录数据库&#x1f3af; su - oracle &#xff08;如果是WINdows系统的CMD窗口&#xff09;直接从第二步开始&#xff01; &#x1f3af;第二步&#xff1a;进入…

【MySQL】视图特性

目录 MySQL视图特性 基本使用 准备测试表 创建视图 修改视图影响基表 修改基表影响视图 删除视图 视图规则和限制 MySQL视图特性 视图的概念 视图是一个虚拟表&#xff0c;其内容由查询定义&#xff0c;同真实的表一样&#xff0c;视图包含一系列带有名称的列和行数据。…

vue,前端打包项目、部署上线

前端项目是在本地的IDE开发的。流程是&#xff1a;开发》打包》上线到生产环境》使用。 vue脚手架只是开发过程中,协助开发的工具,当真正开发完了&#xff0c;脚手架不参与上线。 这时候要用到打包了。 打包后,可以生成,浏览器能够直接运行的网页>就是需要上线的源码! 打…

一个基于人工智能的视频分析和管理工具——Chat Video

Chat Video是一个基于人工智能的视频分析和管理工具&#xff0c;致力于帮助用户高效学习和管理视频。在这个视频泛滥的时代&#xff0c;Chat Video 凭借其独特的AI技术&#xff0c;为用户节省大量时间&#xff0c;真正释放视频的价值。 Chat Video 通过语音识别技术&#xff0…

C语言快捷键+一堆宝藏技巧,全网最全~

&#x1f308;write in front&#x1f308; &#x1f9f8;大家好&#xff0c;我是Aileen&#x1f9f8;.希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流. &#x1f194;本文由Aileen_0v0&#x1f9f8; 原创 CSDN首发&#x1f412; 如…

10.8流水灯

.text .global _start _start: 1.设置GPIOE寄存器的时钟使能 RCC_MP_AHB4ENSETR[4]->1 0x50000a28 LDR R0,0X50000A28 LDR R1,[R0] 从r0为起始地址的4字节数据取出放在R1 ORR R1,R1,#(0x1<<4) 第4位设置为1 STR R1,[R0] 写回1.设置GPIOF寄存器的时钟使能 R…

Linux通过QQ邮箱账号使用mailx发送邮件

Linux通过QQ邮箱账号使用mailx发送邮件 第一步&#xff1a;安装mailx 第二步&#xff1a;获取邮箱的授权码 第三步&#xff1a;配置mailx服务 第四步&#xff1a;添加数字证书 第五步&#xff1a;发送邮件测试&#xff01; 第一步&#xff1a;安装mailx # 安装mailx yum…

1688商品详情数据接口,1688商品详情API接口申请指南

1688商品详情通常包括以下几个部分1&#xff1a; 商品主图&#xff1a;商品的展示图片&#xff1b;商品标题&#xff1a;商品的名字&#xff1b;价格&#xff1a;商品的价格&#xff1b;销量&#xff1a;商品的销量&#xff1b;商品描述&#xff1a;对商品功能的介绍&#xff…

flink双流join结果数据重复问题排查

1.背景 Kafka的两个topic&#xff0c;topic1 为用户下单明细记录&#xff08;包含订单基本信息&#xff09;&#xff0c;topic2为下单渠道记录&#xff08;包含下单来源和渠道内容设备相关的信息&#xff09; &#xff0c;要求实时统计每分钟内所有订单下的渠道来源分布详情。具…

异步爬虫实战:实际应用asyncio和aiohttp库构建异步爬虫

在网络爬虫的开发中&#xff0c;异步爬虫已经成为一种非常流行的技术。它能够充分利用计算机的资源&#xff0c;提高爬虫效率&#xff0c;并且能够处理大量的运算请求。Python中的asyncio和aiohttp库提供了强大的异步爬虫支持&#xff0c;使得开发者能够轻松构建高效的异步爬虫…

springboot+java+ssm高校学生学籍档案信息管理系统3cvy3

本文通过采用B/S架构&#xff0c;MVC开发模式、MySQL数据库以及JSP技术&#xff0c;结合国内学籍管理系统管理现状&#xff0c;开发了一个JSP学籍管理系统。系统前台分为四个功能模块:学院信息、课程信息、专业信息、校园公告。系统后台管理员分为十二个功能模块:首页、个人中心…

数字IC前端学习笔记:数字乘法器的优化设计(Dadda Tree乘法器)

相关阅读 数字IC前端https://blog.csdn.net/weixin_45791458/category_12173698.html?spm1001.2014.3001.5482 华莱士树仍然是一种比较规则的结构&#xff08;这使得可以方便地生成树的结构&#xff09;&#xff0c;这导致了它所使用的全加器和半加器个数不是最少的&#xff…

Step1:走进Java

文章目录 1.1 概述1.2 Java技术体系1.3 Java虚拟机家族1.4 作业:自己编译JDK1.1 概述 Java不仅仅是一门编程语言,它还是一个由一系列计算机软件和规范组成的技术体系,这个技术体系提供了完整用于软件开发和跨平台部署的支持环境,并广泛应用于嵌入式系统、移动终端、企业服…

抖音seo源码开发部署搭建分享--SaaS

应用场景&#xff1a;抖音seo源码&#xff0c;抖音矩阵源码&#xff0c;短视频seo源码&#xff0c;短视频矩阵系统 一、抖音seo源码系统开发需求设计 系统架构&#xff1a;包括系统环境、技术栈、框架等。数据存储&#xff1a;如数据库类型、数据表设计、字段设计等。API接口&…

使用Python进行广告点击率预测

广告点击率是指有多少用户点击了您的广告与有多少用户查看了您的广告的比率。例如&#xff0c;100个用户中有5个在观看XX视频时点击了广告。因此&#xff0c;在这种情况下&#xff0c;XX广告的CTR将是5%。分析点击率有助于公司为目标受众找到最佳广告。所以&#xff0c;如果你想…

一文带你了解三大开源关系型数据库:SQLite、MySQL和PostgreSQL

目录 1、概述 2、SQLite数据库 2.1、SQLite简介 2.2、SQLite优缺点 2.3、SQLite应用场景 3、MySQL数据库 3.1、MySQL简介 3.2、MySQL优缺点 3.3、MySQL应用场景 4、PostgreSQL数据库 4.1、PostgreSQL简介 4.2、PostgreSQL优势 4.3、PostgreSQL应用场景 5、在实际…

【操作系统】聊聊不可中断进程和僵尸进程

当我们输入top命令之后 其中S代表的是当前进程的状态 R (Running 或 Runnable) 进程在CPU的就绪队列中&#xff0c;正在运行或者等待运行。D (Disk Sleep) 不可中断睡眠&#xff0c;进程正在跟硬件交互&#xff0c;不运行被其他进程或者中断打断。Z (Zombie) 进程已经结束&am…

NICE-SLAM——论文简析

NICE-SLAM: Neural Implicit Scalable Encoding 现有的神经隐式表征方法会产生过度平滑的场景重建&#xff0c;并且难以扩展到大型场景。这些局限性主要是由于其简单的全连接网络架构没有将局部信息纳入观测。NICE-SLAM通过引入分层场景表示法&#xff0c;纳入了多层次的局部信…

2019架构真题2020案例(四十七)

数据存储在中央仓库&#xff0c;处理流程独立&#xff0c;交互性好数据和处理耦合在一起&#xff0c;每次修改需要重启劣势&#xff1a;需要通过连接组件进行连接&#xff0c;性能降低优势&#xff1a;支持并发通过仓库连接组件访问&#xff0c;效率高 (8分)缓存中存储当前的热…

基于Java的考试报名系统设计与实现(亮点:可修改任意形式的考试报名,如驾校考试报名、竞赛考试报名、英语四级考试报名等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…