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

目录

前言

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

总结

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

python用户管理系统(加密)

在用户管理系统中使用哈希算法对用户密码进行加密处理 import hashlibusers []# 用户类&#xff0c;包含基本信息 class User:def __init__(self, name, password, emailNone):self.name nameself.password self._encrypt_password(password) # 加密密码self.email email…

ViveNAS性能调试笔记(一)

ViveNAS是一个开源的NAS文件服务软件&#xff0c;有一套独立自创的架构&#xff0c;ViveNAS希望能做到下面的目标&#xff1a; - 能支持混合使用高性能的介质(NVMe SSD)和低性能介质&#xff08;HDD&#xff0c;甚至磁带&#xff09;。做到性能、成本动态均衡。因此ViveNAS使用…

力扣刷题Days28-第二题-11.盛水最多的容器(js)

目录 1&#xff0c;题目 2&#xff0c;代码 3&#xff0c;学习与总结 3.1思路回顾 1&#xff0c;如何遍历 2&#xff0c;算法流程 3.2剖析问题 1&#xff0c;题目 给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, h…

WordPress AutomaticPlugin SSRF漏洞复现(CVE-2024-27954)

0x01 产品简介 WordPress是一款免费开源的内容管理系统(CMS),最初是一个博客平台,但后来发展成为一个功能强大的网站建设工具,适用于各种类型的网站,包括个人博客、企业网站、电子商务网站等,并逐步演化成一款内容管理系统软件。 0x02 漏洞概述 WordPress AutomaticPlu…

jsp中设置动态时间

第一步 在head中写入meta <head><meta charset"UTF-8" http-equiv"Refresh" content"1"> </head> 第二步在head中写入函数 <head><meta charset"UTF-8" http-equiv"Refresh" content"…

网站可扩展架构设计——领域驱动设计(上)

从公众号转载&#xff0c;关注微信公众号掌握更多技术动态 --------------------------------------------------------------- 一、【DDD】领域驱动设计简介 1.什么是DDD——应对复杂性的利器 DDD不是架构&#xff0c;而是一种架构设计方法论&#xff0c;它通过划分领域边界…

HarmonyOS实战开发-一次开发,多端部署-音乐专辑

简介 基于自适应和响应式布局&#xff0c;实现一次开发、多端部署音乐专辑页面。 相关概念 一次开发&#xff0c;多端部署&#xff1a;一套代码工程&#xff0c;一次开发上架&#xff0c;多端按需部署。支撑开发者快速高效的开发支持多种终端设备形态的应用&#xff0c;实现对…

【算法】记忆化搜索

概念 举例 拿斐波那契数列举例 可以发现一般的求解过程中&#xff0c;有很多重复的子问题&#xff0c;递归的本质就是深度优先遍历&#xff0c;如果此时我们可以记录下此时的值然后记录在哈希表中&#xff0c;下一次递归前先去哈希表中查找如果有该值的答案直接返回即可。 这…

大数据 - Hadoop系列《五》- HDFS文件块大小及小文件问题

系列文章&#xff1a; 大数据- Hadoop入门-CSDN博客 大数据 - Hadoop系列《二》- Hadoop组成-CSDN博客 大数据 - Hadoop系列《三》- HDFS&#xff08;分布式文件系统&#xff09;概述_大量小文件的存储使用什么分布式文件系统-CSDN博客 大数据 - Hadoop系列《三》- MapRedu…

[flink 实时流基础] flink 源算子

学习笔记 Flink可以从各种来源获取数据&#xff0c;然后构建DataStream进行转换处理。一般将数据的输入来源称为数据源&#xff08;data source&#xff09;&#xff0c;而读取数据的算子就是源算子&#xff08;source operator&#xff09;。所以&#xff0c;source就是我们整…

PostCSS的安装及使用(1):安装

在不同操作系统上安装PostCSS的步骤大致相同&#xff0c;因为PostCSS是基于Node.js的一个JavaScript工具&#xff0c;是依赖于Node.js环境和npm&#xff08;Node包管理器&#xff09;。 PostCSS官网&#xff1a; GitHub地址&#xff1a; GitHub - postcss/postcss: Transformi…

WebScraper网页数据爬取可视化工具使用(无需编码)

前言 Web Scraper 是一个浏览器扩展&#xff0c;可以实现无需编码即可爬取网页上的数据。只需按照规则进行配置&#xff0c;即可实现一键爬取导出数据。 安装 进入Google应用商店安装此插件&#xff0c;安装步骤如下&#xff1a; 进入Google应用商店需要外网VPN才能访问&…

学生寝室恶性负载识别模块

学生寝室恶性负载识别模块系统是石家庄光大远通电气公司一种专门用于学生寝室电力管理的系统&#xff0c;旨在识别并限制使用违规或高风险的电器设备&#xff0c;以保障学生的用电安全和节约能源。该系统通过先进的电力检测技术和算法&#xff0c;能够实时监测寝室内的电力使用…

react ts 封装搜索条件

封装 import React, { ReactNode, useImperativeHandle, forwardRef } from react; import { Card, Form, Input, Button, Row, Col } from antd;interface Iprops {formItem: any,getParams: (params: any) > void,reset?: () > void | undefined,isButton?: boolean…

MySQL学习之连接查询

笛卡尔乘积现象 在表的连接查询方面有一种现象被称为&#xff1a;笛卡尔积现象。 笛卡尔积现象&#xff1a; 当两张表进行连接查询的时候&#xff0c;没有任何条件进行限制&#xff0c;最终的查询结果条数是两张表记录条数的乘积。 select ename,dname from emp,dept; 避免…

YOLOV5训练自己的数据集教程(万字整理,实现0-1)

文章目录 一、YOLOV5下载地址 二、版本及配置说明 三、初步测试 四、制作自己的数据集及转txt格式 1、数据集要求 2、下载labelme 3、安装依赖库 4、labelme操作 五、.json转txt、.xml转txt 六、修改配置文件 1、coco128.yaml->ddjc_parameter.yaml 2、yolov5x.…

如何制作伸缩侧边栏?

目录 一、html-body 二、CSS 三、JS 四、完整代码 五、效果展示 一、html-body 侧边栏的伸缩需要用户触发事件&#xff0c;这里使用button为例&#xff0c;用户点击按钮实现侧边栏的打开和关闭。 <body><!-- 按钮&#xff0c;可以用文字、图片等作为事件源&am…

wails 创建Go 项目

##wails是一个可以让go和web技术编写桌面应用#安装wails go install github.com/wailsapp/wails/v2/cmd/wailslatest#检查环境 wails doctor 创建项目wails init -n AuxiliaryTools -t vue-ts拉取go.mod的依赖项 go mod tidy进入 frontend 前端安装依赖项npm install /pnpm ins…

透视未来安全:PIR技术引领数据隐私新时代

1.隐语实现PIR总体介绍 隐语实现的Private Information Retrieval (PIR) 是一种隐私增强技术&#xff0c;它使用户能够在不暴露他们实际查询内容的情况下从远程服务器数据库中检索所需信息。以下是隐语在实现PIR方面的概要说明和技术特点&#xff1a; 基本概念&#xff1a; PI…

Arcgis根据要素面获取要素中心点并计算中心点坐标

一、要素面获取要素中心点 1、加载数据 2、找到“要素转点”工具 打开ArcTool box工具&#xff0c;数据管理工具—要素—要素转点&#xff0c;或者打开搜索器直接搜索“要素转点”即可 3、要素转点 弹出转换界面之后&#xff0c;输入面状要素&#xff0c;设置保存路径&#…