动态内存管理(1)
目录
1. 为什么存在动态内存分配
2. 动态内存函数的介绍
2.2 calloc
2.3 realloc
3. 常见的动态内存错误
3.1 对NULL指针的解引用操作
3.2 对动态开辟空间的越界访问
3.3 对非动态开辟内存使用free释放
3.4 使用free释放一块动态开辟内存的一部分
3.5 对同一块动态内存多次释放
3.6 动态开辟内存忘记释放(内存泄漏)
1. 为什么存在动态内存分配
我们已经掌握的内存开辟方式有:
int val = 20;//在栈空间上开辟四个字节
char arr[10] = {0};//在栈空间上开辟10个字节的连续空间
但是上述的开辟空间的方式有两个特点:
1. 空间开辟大小是固定的。
2. 数组在申明的时候,必须指定数组的长度,它所需要的内存在编译时分配。
但是对于空间的需求,不仅仅是上述的情况。有时候我们需要的空间大小在程序运行的时候才能知道, 那数组的编译时开辟空间的方式就不能满足了。
这时候就只能试试动态存开辟了。
2. 动态内存函数的介绍
2.1 malloc和free
void* malloc (size_t size);
这个函数向内存申请一块连续可用的空间,并返回指向这块空间的指针。
如果开辟成功,则返回一个指向开辟好空间的指针。
如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。
返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己 来决定。
如果参数 size 为0,malloc的行为是标准是未定义的,取决于编译器。
#include<stdio.h>
#include<stdlib.h>
#include<limits.h>int main()
{//申请一块空间,用来存放10个整型//int* p = (int*)malloc(INT_MAX*4);int* p = (int*)malloc(10 * sizeof(int));if (p == NULL){perror("malloc");return 1;}return 0;
}
free函数用来释放动态开辟的内存。
如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的。
如果参数 ptr 是NULL指针,则函数什么事都不做。
#include <stdio.h>
int main()
{//代码1int num = 0;scanf("%d", &num);int arr[num] = {0};//代码2int* ptr = NULL;ptr = (int*)malloc(num*sizeof(int));if(NULL != ptr)//判断ptr指针是否为空{int i = 0;for(i=0; i<num; i++){*(ptr+i) = 0;}}free(ptr);//释放ptr所指向的动态内存ptr = NULL;//是否有必要?return 0;
}
2.2 calloc
C语言还提供了一个函数叫 calloc , calloc 函数也用来动态内存分配。原型如下:
void* calloc (size_t num, size_t size);
函数的功能是为 num 个大小为 size 的元素开辟一块空间,并且把空间的每个字节初始化为0。
与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0。 举个例子:
int main()
{int* p = malloc(10 * sizeof(int));if (p == NULL){perror("malloc");return 1;}//打印int i = 0;for (i = 0; i < 10; i++){printf("%d\n", *(p + i));}//释放free(p);p = NULL;return 0;
}
2.3 realloc
realloc函数的出现让动态内存管理更加灵活。
有时会我们发现过去申请的空间太小了,有时候我们又会觉得申请的空间过大了,那为了合理的时 候内存,我们一定会对内存的大小做灵活的调整。
那 realloc 函数就可以做到对动态开辟内存大小 的调整。
函数原型如下:
void* realloc (void* ptr, size_t size);
ptr 是要调整的内存地址 size 调整之后新大小 返回值为调整之后的内存起始位置。
这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到 新 的空间。
realloc在调整内存空间的是存在两种情况:
情况1:原有空间之后有足够大的空间
情况2:原有空间之后没有足够大的空间
情况1 当是情况1 的时候,要扩展内存就直接原有内存之后直接追加空间,原来空间的数据不发生变化。
情况2 当是情况2 的时候,原有空间之后没有足够多的空间时,扩展的方法是:在堆空间上另找一个合适大小 的连续空间来使用。这样函数返回的是一个新的内存地址。
由于上述的两种情况,realloc函数的使用就要注意一些。
int main()
{int* p = calloc(10, sizeof(int));if (p == NULL){perror("calloc");return 1;}int i = 0;for (i = 0; i < 10; i++){p[i] = i;}//打印for (i = 0; i < 10; i++){printf("%d\n", *(p + i));}//空间不够,希望调整空间为20个整型的空间int* ptr = (int*)realloc(p, 2000*sizeof(int));if (ptr != NULL){p = ptr;}//...//释放free(p);p = NULL;return 0;
}
3. 常见的动态内存错误
3.1 对NULL指针的解引用操作
void test()
{int *p = (int *)malloc(INT_MAX/4);*p = 20;//如果p的值是NULL,就会有问题free(p);
}
3.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);
}
3.3 对非动态开辟内存使用free释放
void test()
{int a = 10;int *p = &a;free(p);//ok?
}
3.4 使用free释放一块动态开辟内存的一部分
void test()
{int *p = (int *)malloc(100);p++;free(p);//p不再指向动态内存的起始位置
}
3.5 对同一块动态内存多次释放
void test()
{int *p = (int *)malloc(100);free(p);free(p);//重复释放
}
3.6 动态开辟内存忘记释放(内存泄漏)
void test(){int *p = (int *)malloc(100);if(NULL != p){*p = 20;}
}
int main()
{test();while(1);
}
忘记释放不再使用的动态开辟的空间会造成内存泄漏。
切记:
动态开辟的空间一定要释放,并且正确释放
相关文章:
动态内存管理(1)
目录 1. 为什么存在动态内存分配 2. 动态内存函数的介绍 2.2 calloc 2.3 realloc 3. 常见的动态内存错误 3.1 对NULL指针的解引用操作 3.2 对动态开辟空间的越界访问 3.3 对非动态开辟内存使用free释放 3.4 使用free释放一块动态开辟内存的一部分 3.5 对同一块动…...
ThunderSearch(闪电搜索器)_网络空间搜索引擎工具_信息收集
文章目录 ThunderSearch简介1 项目地址2 使用方式2.1 配置文件config.json说明2.2 构建和运行 3 使用式例 ThunderSearch简介 ThunderSearch(闪电搜索器)是一款使用多个(【支持Fofa、Shodan、Hunter、Zoomeye、360Quake网络空间搜索引擎】网络空间搜索引…...
Topaz Video AI 视频修复工具(内附安装压缩包win+Mac)
目录 一、Topaz Video AI 简介 二、Topaz Video AI 安装下载 三、Topaz Video AI 使用 最近玩上了pika1.0和runway的图片转视频,发现生成出来的视频都是有点糊的,然后就找到这款AI修复视频工具 Topaz Video AI。 一、Topaz Video AI 简介 Topaz Video…...
android内存管理机制概览
关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 ,擅长java后端、移动开发、人工智能等,希望大家多多支持。 目录 一、导读二、概览三、相关概念3.1 垃圾回收3.2 应用内存的分配与回…...
下载MySQL Connector/C++
MySQL :: Download Connector/C...
ai gpt 鸡皮剔提问技巧
请将如下AB两组信息逐个匹配上的进行同类归类,用json格式输出: A:苹果 电脑 汽车 B: 猕猴桃 笔记本 根据你的要求,逐个匹配 A 组和 B 组的元素,并以 JSON 格式输出同类的归类信息: json { "匹配信息"…...
详谈 springboot整合shiro
背景: 本章将进一步的落地实践学习,在springboot中如何去整合shrio,整个过程步骤有个清晰的了解。 利用Shiro进行登录认证主要步骤: 1. 添加依赖:首先,在pom.xml文件中添加Spring Boot和Shiro的相关依赖…...
备忘录模式(Memento)
备忘录模式(Memento Pattern)是一种行为型设计模式,允许在不破坏封装的前提下捕获并保存一个对象的内部状态,以便在以后可以将该对象恢复到原先保存的状态。 备忘录模式通常涉及以下几个角色: 发起人(Originator):创建一个含有其当前状态的备忘录对象,并可以使用备忘录…...
【RocketMQ每日一问】consumeGroup心跳内容是什么样的?
消费者组:消费者所在的消费者组名称。这个信息用于确保同一个消费者组内的消费者不会重复地消费相同的消息。MessageModel:消息模型,可能的值为集群消费或广播消费。ConsumeType:消费类型,可能的值有"主动消费&qu…...
yolov5知识蒸馏
参考代码:https://github.com/Adlik/yolov5 https://cloud.tencent.com/developer/article/2160509 yolov5间的模型蒸馏,相同结构的。 配置参数 parser.add_argument(--t_weights, typestr, default./weights/yolov5s.pt,helpinitial teacher model wei…...
HUAWEI华为笔记本电脑MateBook D 14 2022款 i5 集显 非触屏(NbDE-WFH9)原装出厂Windows11系统21H2
链接:https://pan.baidu.com/s/1-tCCFwZ0RggXtbWYBVyhFg?pwdmcgv 提取码:mcgv 华为MageBookD14原厂WIN11系统自带所有驱动、出厂状态主题壁纸、Office办公软件、华为电脑管家、华为应用市场等预装软件程序 文件格式:esd/wim/swm 安装方式…...
微服务-springcloud(eureka实践, nacos实践)
Spring 体系图 版本关系 eureka 实践 1 父工程依赖 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.14</version> </parent> <dependencyManage…...
Hadoop入门学习笔记——五、在虚拟机中部署Hive
视频课程地址:https://www.bilibili.com/video/BV1WY4y197g7 课程资料链接:https://pan.baidu.com/s/15KpnWeKpvExpKmOC8xjmtQ?pwd5ay8 Hadoop入门学习笔记(汇总) 目录 五、在虚拟机中部署Hive5.1. 在node1虚拟机安装MySQL5.2.…...
用Nest 实现大文件分片上传,加速工作效率神器
文件上传是常见需求,只要指定 content-type 为 multipart/form-data,内容就会以这种格式被传递到服务端: 服务端再按照 multipart/form-data 的格式提取数据,就能拿到其中的文件。 但当文件很大的时候,事情就变得不一样…...
将ncnn及opencv的mat存储成bin文件的方法
利用fstream,将ncnn及opencv的mat存储成bin文件。 ncnn::Mat to bin std::ios::binary标志指示文件以二进制模式进行读写, std::ofstream file("output_x86.bin", std::ios::binary); 将input_mat中的宽、高和通道数分别赋值给width、heig…...
dpdk原理概述及核心源码剖析
dpdk原理 1、操作系统、计算机网络诞生已经几十年了,部分功能不再能满足现在的业务需求。如果对操作系统做更改,成本非常高,所以部分问题是在应用层想办法解决的,比如前面介绍的协程、quic等,都是在应用层重新开发的框…...
VTK+QT配置(VS)
先根据vtk配置这个博客配置基本环境 然后把这个dll文件从VTK的designer目录复制到qt的对应目录里 记得这里是debug版本,你也可以配置release都一样的步骤,然后建立一个qt项目,接着配置包含目录,库目录,链接输入&…...
5G边缘计算:解密边缘计算的魔力
引言 你是否曾想过,网络可以更贴心、更智能地为我们提供服务?5G边缘计算就像是网络的小助手,时刻待命在你身边,让数字生活变得更加便捷。 什么是5G边缘计算? 想象一下,边缘计算就像是在离你最近的一层“云…...
Sentinel 流量治理组件教程
前言 官网首页:home | Sentinel (sentinelguard.io) 随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量路由、流量控制、流量整形…...
C语言第五十九弹---介绍说明内存函数memcmp
使用C语言介绍说明内存函数memcmp memcmp是C语言标准库中的一个函数,用于比较两个内存区域的内容是否相同。 源代码: int memcmp(const void* ptr1, const void* ptr2, size_t num);ptr1和ptr2分别是要比较的两个内存区域的指针,num是要比较…...
地震勘探——干扰波识别、井中地震时距曲线特点
目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波:可以用来解决所提出的地质任务的波;干扰波:所有妨碍辨认、追踪有效波的其他波。 地震勘探中,有效波和干扰波是相对的。例如,在反射波…...
智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql
智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...
【项目实战】通过多模态+LangGraph实现PPT生成助手
PPT自动生成系统 基于LangGraph的PPT自动生成系统,可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析:自动解析Markdown文档结构PPT模板分析:分析PPT模板的布局和风格智能布局决策:匹配内容与合适的PPT布局自动…...
ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...
深度学习水论文:mamba+图像增强
🧀当前视觉领域对高效长序列建模需求激增,对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模,以及动态计算优势,在图像质量提升和细节恢复方面有难以替代的作用。 🧀因此短时间内,就有不…...
