C语言:动态内存管理(二)

news2024/11/25 2:38:07

目录

前言

1.3 realloc​编辑

3、常见动态内存管理错误

3.1 对空指针的解引用操作

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

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

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

3.5 对同一块空间的多次释放

3.6 动态内存开辟之后忘记释放

总结


前言

        接上篇继续往下将。

1.3 realloc

        realloc是调整内存空间的函数,就是用来调整内存空间的大小。参数有两个,第一个参数是指向要调整空间的起始位置;第二个参数是新的大小,希望把原来的空间调整到多大,这里就填多少(直接)。

        下面看一个例子:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
int main()
{
	int* p = (int*)malloc(40);
	if (NULL == p)
	{
		printf("%s", strerror(errno));
		return 1;
	}
	//使用
	int i = 0;
	for (i = 0;i < 10;i++)
	{
		*(p + i) = i + 1;
	}
	for (i = 0;i < 10;i++)
	{
		printf("%d ", *(p + i));
	}
	//扩容
	int* pn = (int*)realloc(p, 80);
	if (pn != NULL)
	{
		p = pn;
	}
	//使用
	printf("\n");
	for (i = 0;i < 20;i++)
	{
		*(p + i) = i + 1;
	}
	for (i = 0;i < 20;i++)
	{
		printf("%d ", *(p + i));
	}
	return 0;
}

        在这个例子里面,我们首先用malloc建立了一块大小为40字节的空间,赋值10个整型,观察输出;后又用realloc将原有空间扩大到80字节,最后对空间赋值了20个整型,观察输出。我们来看看运行结果:

        可以看到,realloc成功将原有的40字节空间扩大到了80字节,以便我们存放20个整型数据。

        在这里要注意的是,在扩容时(也就是使用realloc函数时),我们要对新产生的指针进行判断,因为有可能扩容空间太大导致开辟不成功,计算机会返回空指针。所以有了上面的两行代码:

	int* pn = (int*)realloc(p, 80);
	if (pn != NULL)
	{
		p = pn;
	}

        这样能保证在扩容不成功的情况下,p指针还能保留原来40字节空间及其内容。

        关于realloc的功能,除了能对内存进行扩容以外,还可以进行空间开辟,只需要在传递指针参数的时候传递一个空指针即可。如果这么做,那么它的功能就相当于malloc。

        realloc就讲到这了。

3、常见动态内存管理错误

3.1 对空指针的解引用操作

        以前一篇里面对malloc的使用代码为例:

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>

int main()
{
	//动态内存开辟
	int* p = (int*)malloc(40);
	if (p == NULL)	//判断是否开辟成功,开辟失败就报错。
	{
		printf("%s\n", strerror(errno));
		return 1;
	}
	//使用
	int i = 0;
	for (i = 0;i < 10;i++)
	{
		*(p + i) = i;
	}
	for (i = 0;i < 10;i++)
	{
		printf("%d ", *(p + i));
	}

    //空间释放
    free(p);
	p = NULL;

	return 0;
}

        我们在使用之前,先要对定义的p进行判断,看malloc是否成功开辟空间。如果申请空间太大了超过了计算机能承担的范围,就会开辟失败,那malloc返回的将会是一个空指针,p也就为空,那我们如果不加判断直接使用p的时候,就会对其进行接引用,这样做就很危险。

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

        动态开辟的空间也是有大小的,假设我们用malloc开辟了一个40字节的空间,那么对于整型变量,最多存放10个,当我们去访问第11个整型的时候,就会造成越界访问。

        动态内存虽然叫动态内存,但它是需要我们自己去操作才能实现动态的效果的,比如上面说的,如果要去存放第11个整型,我们只需要用到calloc对原来的内存进行加长,就可以了。

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

        对于free这个函数,它只能配合函数malloc、calloc、raelloc使用,对于一般的指针指向的内容,是不能用free释放的。原因在于,malloc、calloc、realloc函数创建的内存其实和一般的变量创建的内存的位置不一样,前者在堆区,后者在栈区,他们是有区别的。一旦用free去释放一个非动态开辟的内存时,就会报错。

        例如:

int main()
{
	int a = 10;
	int* p = &a;

	free(p);
	p = NULL;
	return 0;
}

        这样的程序一旦运行,就会报错。

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

        直接上例子:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
int man()
{
	int* p = (int*)malloc(40);
	if (NULL == p)
	{
		printf("%s", strerror(errno));
		return 1;
	}
	//使用
	int i = 0;
	for (i = 0;i < 10;i++)
	{
		*p = i;
		p++;
	}

	//释放
	free(p);
	p = NULL;

	return 0;
}

        像这样的程序,当我们使用完p之后,p将会指向malloc开辟的空间的第十个元素的位置,这时候对p进行free是不行的,如果要用free,就要一次性将整个malloc开辟的空间进行释放,指针必须是指向这块空间的首元素的。

3.5 对同一块空间的多次释放

        这个比较好理解,我们可能会对同一块空间多次释放,这时候也是会报错的。因为第一次释放后指针指向的空间已经被回收了,但是指针任然指向原来的地址,它变成了一个野指针,再一次释放就找不到空间去释放。但如果我们在释放空间后顺便把指针指向空指针,那么再释放一次就也没有问题了。

3.6 动态内存开辟之后忘记释放

        每一次用malloc、calloc、realloc开辟动态内存的时候,在使用完成后,一定记得对其进行释放,做事情要有头有尾。如果忘记释放的话,就会造成内存泄漏,在整个程序结束前,这块内存会一直被占用,在程序结束前都无法再利用这块空间。这样的内存多了,就会导致计算机性能下降 。

总结

        关于动态内存管理的内容就讲到这。希望对你有所帮助。

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

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

相关文章

前端三剑客 —— HTML (下)

目录 HTML 多媒体标签 Img*** a标签*** 第一种用法&#xff1a;超链接 第二种用法&#xff1a;锚点 audio标签 video标签 表格标签 带标题的表格 跨行跨列标签 表格嵌套 列表标签 ul --- 它是无序列表标签 ol --- 它是有序列表 dl --- 它是数据列表 表单标签***…

2024.3.30学习笔记

今日学习韩顺平java0200_韩顺平Java_对象机制练习_哔哩哔哩_bilibili 今日学习p295-p314 super关键字 super代表父类的引用&#xff0c;用于访问父类的属性、方法、构造器 super细节和语法 访问父类的属性&#xff0c;但不能访问父类的private属性 super.属性名 访问父类的…

暴力破解pdf文档密码

首先安装pdfcrack工具包 apt install pdfcrack 默认密码字典存储在/usr/share/wordlists里&#xff0c;是gz文件&#xff0c;将它解压并copy到pdf目录 然后使用pdfcrack破解 密码在最后一行user-password的单引号里

最优算法100例之17- 环形连续子数组的最大和

专栏主页:计算机专业基础知识总结(适用于期末复习考研刷题求职面试)系列文章https://blog.csdn.net/seeker1994/category_12585732.html 题目描述 给定一个长度为 nn 的环形整数数组,请你求出该数组的 非空 连续子数组 的最大可能和 。 环形数组 意味着数组的末端将会与开…

Linux重点思考(下)--shell脚本使用以及内核开发

Linux重点思考(下&#xff09;--shell脚本使用和组合拳 shell脚本的基础算法shell脚本写123...n的值&#xff0c;说思路Shell 脚本用于执行服务器性能测试的死循环Shell 脚本备份和定时清理垃圾文件 shell脚本的内核开发正向映射反向映射 shell脚本的基础算法 shell脚本写123……

解决MySQL幻读?可重复读隔离级别背后的工作原理

什么是当前读和快照读 当前读&#xff1a;又称为 "锁定读"&#xff0c;它会读取记录的最新版本&#xff08;也就是最新的提交结果&#xff09;&#xff0c;并对读取到的数据加锁&#xff0c;其它事务不能修改这些数据&#xff0c;直到当前事务提交或回滚。"sele…

linux服务器安装mysql8

1.下载MYSQL 近几天在linux服务器已安装过2次mysql8&#xff0c;亲测有效&#xff0c;没有遇到任何问题&#xff0c;文档已写的很清楚&#xff0c;按步骤来即可。如果按文档有遇到要使用yum命令的话&#xff0c;需要服务器开通外网。 1.1官网下载 进入官网下拉到最后&#x…

【查看显卡信息】如何查看nvidia-smi命令后的显卡信息

【查看显卡信息】如何查看nvidia-smi命令后的显卡信息 【先赞后看养成习惯】求点赞关注收藏&#xff01;&#xff01;&#xff01;&#x1f60a; 一般我们用nvidia-smi进行查看当前电脑或者服务器的显卡信息&#xff0c;出来一大堆内容&#xff0c;很多小白根本看不懂&#xf…

elementui 导航菜单栏和Breadcrumb 面包屑关联

系列文章目录 一、elementui 导航菜单栏和Breadcrumb 面包屑关联 文章目录 系列文章目录前言一、elementui 导航菜单栏和Breadcrumb 面包屑怎么关联&#xff1f;二、实现效果三、实现步骤1.本项目演示布局2.添加面包屑2.实现breadcrumbName方法3.监听方法4.路由指配5.路由配置…

大数据设计为何要分层,行业常规设计会有几层数据

大数据设计通常采用分层结构的原因是为了提高数据管理的效率、降低系统复杂度、增强数据质量和可维护性。这种分层结构能够将数据按照不同的处理和应用需求进行分类和管理&#xff0c;从而更好地满足不同层次的数据处理和分析需求。行业常规设计中&#xff0c;数据通常按照以下…

R语言颜色细分

1.如何对R语言中两种颜色之间进行细分 2.代码&#xff1a; x <- colorRampPalette(c("#FC8D62","#FDEAE6"))(12) #打印向量值 # 按字典顺序排序颜色值 x_sorted <- sort(x,decreasing TRUE)# 打印排序后的颜色值 print(x_sorted)#展示颜色 scales:…

websocket 局域网 webrtc 一对一 视频通话的实例

基本介绍 使用websocket来 WebRTC 建立连接时的 数据的传递和交换。 WebRTC 建立连接时&#xff0c;通常需要按照以下顺序执行一些步骤&#xff1a; 1.创建本地 PeerConnection 对象&#xff1a;使用 RTCPeerConnection 构造函数创建本地的 PeerConnection 对象&#xff0c;该…

springboot企业级抽奖项目业务四 (缓存预热)

缓存预热 为什么要做预热: 当活动真正开始时&#xff0c;需要超高的并发访问活动相关信息 必须把必要的数据提前加载进redis 预热的策略: 在msg中写一个定时任务 每分钟扫描一遍card_game表 把(开始时间 > 当前时间)&& (开始时间 < 当前时间1分钟)的活动及相…

(八)Gateway服务网关

Gateway服务网关 Spring Cloud Gateway 是 Spring Cloud 的一个全新项目&#xff0c;该项目是基于 Spring 5.0&#xff0c;Spring Boot 2.0 和 Project Reactor 等响应式编程和事件流技术开发的网关&#xff0c;它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。…

day01-SpringCloud01(Eureka、Ribbon、Nacos)

视频地址: SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务 学习资料地址: 百度网盘 提取码&#xff1a;1234 1. 认识微服务 1.1.单体架构 单体架构&#xff1a;将业务的所有功能集中在一个项目中开发&#x…

WebCopilot:一款功能强大的子域名枚举和安全漏洞扫描工具

关于WebCopilot WebCopilot是一款功能强大的子域名枚举和安全漏洞扫描工具&#xff0c;该工具能够枚举目标域名下的子域名&#xff0c;并使用不同的开源工具检测目标存在的安全漏洞。 工具运行机制 WebCopilot首先会使用assetsfinder、submaster、subfinder、accumt、finddom…

【2023】kafka在linux和docker安装(kafka-1)

目录&#x1f4bb; 一、linux安装kafka1. 安装jdk2. 上传解压到/usr/local目录下3、使用kafka 二、docker安装kafka1. 下载2. 安装zookeeper3. 安装kafka 一、linux安装kafka 环境主机 mac m2、虚拟机Ubuntu22.04.4 1. 安装jdk yum install -y java-1.8.0-openjdk.x86_64下载k…

Redis分布式锁红锁

Redisson实现分布式锁 lock()上锁解析&#xff1a; 1&#xff0c;hexist判断redis是否有这个锁 2&#xff0c;hset设置锁&#xff0c;hash类型&#xff0c;key为锁名字&#xff0c;value是一对kv&#xff0c;k是当前redisson1的id,v为计数器&#xff0c;表示当前锁持有次数&am…

【详细讲解语言模型的原理、实战与评估】

&#x1f308;个人主页:程序员不想敲代码啊&#x1f308; &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家&#x1f3c6; &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提…

【苹果MAC】苹果电脑 LOGI罗技鼠标设置左右切换全屏页面快捷键

首先键盘设置->键盘快捷键 调度中心 设置 f1 f2 为移动一个空间&#xff08;就可以快捷移动了&#xff09; 想要鼠标直接控制&#xff0c;就需要下载官方驱动&#xff0c;来设置按键快捷键&#xff0c;触发 F1 F2 安装 LOGI OPTIONS Logi Options 是一款功能强大且便于使用…