动态内存管理(malloc、free、calloc、realloc函数简介)

news2024/11/24 16:44:53

动态内存管理

  • 🎃为什么存在动态内存管理
  • 🎃动态内存函数的介绍
    • 🎊malloc
      • 🎋perror函数
    • 🎊free
    • 🎊calloc
    • 🎊realloc

🎃为什么存在动态内存管理

在此之前,我们开辟内存空间有两种方式。一种是创建一个已知类型的变量。
比如说:

int a=10;  //在栈空间上开辟4个字节

向系统申请了4个字节的内存空间。(对于 int型,4个字节它是固定的。)
还有一种是,创建一个数组。
比如说:

int arr[10]; //在栈空间上开辟40个字节的连续空间。

向系统申请了40个字节的内存空间。当这个数组开辟好了空间,没有办法改变它的大小。
对于数组的创建,它的内存开辟方式是比较死板的。

int arr1[10];

int arr2[100];

我们创建数组时,在一开始时就会指定数组的大小。arr1的内存空间为40个字节,可以存放10个整型元素。arr2的内存空间为400个字节,可以存放100个整型元素。
但有可能我们在使用数组arr1的时候,需要存放11个数组元素,而没有办法把它边长。
我们可能为了尽可能满足很多情况,而创建一个很大的数组arr2,但在实际使用过程中,我们可能只会存放20个元素,而导致了内存空间的浪费。
所以这样的内存开辟方式它是固定的,是不够灵活的
不仅仅是上述的情况,有时候我们需要的空间大小在程序运行的时候才能知道,那么数组在编译时开辟空间的方式就不能满足了。
所以,我们需要学会开辟动态内存

🎃动态内存函数的介绍

malloc
free
calloc
realloc

🎊malloc

malloc函数的原型:

void* malloc(size_t size);

malloc声明在stdlib.h头文件中。
功能:
这个函数向内存申请一块连续可用的空间,并返回指向这块空间的指针

  • 如果开辟成功,则返回指向这块空间的指针。
  • 如果开辟失败,则返回一个NULL指针。

因此,malloc函数的返回值一定要做检查。

举个例子:
原来,我们用数组栈区开辟内存空间:

现在,我们在堆区动态开辟同样大小的内存空间:

根据malloc函数的原型,我们需要传递一个参数,以字节为单位的内存。

malloc(40)//即开辟了40个字节的内存空间

然后,我们需要一个指针p来指向这块儿开辟好的连续的 内存空间
但由于 malloc函数的返回值为 void*,即无类型指针,所以我们需要先进行强制转换,将无类型指针转换为整型指针
因此,

int* p=(int*)malloc(40);

在这里插入图片描述

但是,正如我们上面所提到的,我们只是用malloc函数向内存申请开辟40个自己的连续空间,不一定开辟成功。所以我们需要利用指针p进行进一步检验

若开辟成功,进行访问:

malloc函数 申请的内存空间,但程序退出时,不会主动释放的,需要使用free函数来释放。

🎋perror函数

perror函数(忘的打印输出函数)

来自这篇博客:C语言perror函数详解

🎊free

C语言提供free函数,专门用来做动态内存释放和回收的。
free函数原型:

void free(void *ptr);

free函数也是声明在头文件<stdlib.h>中的。
free函数用来释放动态开辟的内存。

  • 如果参数ptr指向的空间不是动态开辟的,那free函数的行为是未定义的。
  • 如果参数ptr是NULL指针,则函数什么事都不做。

🎊calloc

C语言还提供了一个函数叫calloc,calloc函数也用来动态内存分配。
calloc函数的原型:

void* calloc(size_t num,size_t size);

calloc函数的功能为,为num个大小为size的元素开辟一块空间,并且把每个字节初始化为0。
与函数malloc函数的区别只在于calloc会在返回地址之前把申请的每个字节初始化为0。
即:

#include<stdio.h>
#include<stdlib.h>
int main()
{
	int* p = (int*)calloc(10, sizeof(int));//开辟10个大小为sizeof(int),即4个字节 的空间
	//判断是否开辟成功
	if (p == NULL)
	{
		perror("calloc");
		return 1;
	}

	int i = 0;
	for (i = 0; i < 10; i++)
		printf("%d\n", *(p + i));
	return 0;
}

在这里插入图片描述

🎊realloc

  • realloc函数的出现让动态内存管理更加灵活
    有时候我们发现之前申请的内存过小了,有时候我们发现我们申请的内存过大了,所以,在一些时候,我们需要对内存的大小做灵活的调整。那么realloc函数就可以做到对动态开辟内存大小的调整
    realloc函数的原型如下:
void* realloc(void* ptr,size_t size);

其中,ptr是要调整的内存的地址
size是调整之后的新的内存的大小。
返回值是调整之后内存的起始位置。
这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到的空间。
举个例子:
我们首先使用malloc函数开辟40个字节的空间:

//malloc函数申请空间
int* p = (int*)malloc(40);
if (p == NULL)
{
	perror("malloc");
	return 1;
}
//初始化
int i = 0;
for (i = 0; i < 10; i++)
	*(p + i) = i;

我们想要将这个空间扩大,扩大为80个字节的空间。
于是我们使用realloc函数进行调整。但是内存空间的变化可能有不同的情况。
情况一,后面有足够的空间。
即这样的情形:

情况二,后面没有足够的空间:

//增加一些空间
int *ptr=realloc(p, 80);
if (ptr != NULL)
{
	p = ptr;
}

在用realloc函数调整动态内存空间时,要注意不能将原来的p指针,来接收realloc(p,80)。
这是因为relloc函数不一定开辟成功新的空间而进行调整,即realloc函数的返回值可能为NULL。
那么p=NULL,本来p维护40个字节的空间。那么这样那个40个字节空间的字节就没有指针维护了。但还没有释放,可能用不到了,但可能找不到了,从而造成内存泄露。

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

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

相关文章

shell脚本执行中报错: line 10: 09: value too great for base (error token is “09“)

shell脚本执行中报错&#xff1a; line 10: 09: value too great for base (error token is “09”) 这个错误通常是由于 shell 脚本中对一个数值使用了以零开头的八进制表示方式&#xff0c;而八进制表示中的数字 8 和 9 是无效的引起的。shell 默认将以零开头的数字解释为八进…

【网络安全】你必须知道的几个网络安全概念

一、安全 Web 网关 安全 Web 网关已经从其过去优化互联网带宽的目的演变为保护用户免受来自互联网的恶意内容的侵害。诸如 URL 过滤、反恶意软件、解密和检查通过 HTTPS 访问的网站、数据丢失防护 (DLP) 和云访问安全代理 (CASB) 等功能现已成为标准。 二、 DDoS 防御 DDoS …

在仿真和代码执行期间在参数值集之间切换

目录 浏览模型示例 将参数值存储在结构体数组中 创建变量以在参数集之间切换 使用总线对象作为结构体数组的数据类型 使用枚举类型切换变量 向数据字典添加新对象 仿真期间在参数集之间切换 生成和检查代码 要存储相同模块参数的多个独立值集&#xff0c;可以使用结构体…

局部变量,全局变量与内存

本文会使用IDA分析局部变量&#xff0c;全局变量在内存的存储 目录 使用IDA分析局部变量 使用IDA分析全局变量 总结 使用IDA分析局部变量 #include <stdio.h>int main() {int nNum 1;float fNum 2.5;char ch A;printf("int %d, float %f, char %c", nNu…

华为云云耀云服务器L实例使用教学

随着云计算时代的进一步深入&#xff0c;越来越多的中小企业企业与开发者需要一款简单易用、高能高效的云计算基础设施产品来支撑自身业务运营和创新开发。 基于这种需求&#xff0c;华为云焕新推出华为云云服务器实例新品。 华为云云服务器具有智能不卡顿、价优随心用、上手更…

Python+Django前后端分离

程序示例精选 PythonDjango前后端分离 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对《PythonDjango前后端分离》编写代码&#xff0c;代码整洁&#xff0c;规则&#xff0c;易读。 学习与应…

《语义增强可编程知识图谱SPG》白皮书

语义増强可编程图谱框架&#xff1a;新一代知识图谱语义框架/引擎、SPGLLM双驱架构及应用相关进展和应用。《语义增强可编程知识图谱SPG》白皮书 v1.0.pdf: https://url39.ctfile.com/f/2501739-941002398-f8f1f0?p2096 (访问密码: 2096) 参考文献&#xff1a; [1]《语义增强可…

JavaScript学习笔记04

JavaScript笔记04 方法 定义方法 当一个函数是一个对象的属性时&#xff0c;称之为方法。例&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><script>let p…

“Vim 退出”使百万程序员无所适从

“程序员一旦进入 Vim &#xff0c;就再难以脱身。”这听起来像是一个恐怖故事&#xff0c;但是却真实的发生在程序员的身上&#xff0c; Stack Overflow 上关于如何退出 Vim 的问题&#xff0c;其点击量已有上百万次了。 问题原文为&#xff1a; Im stuck and cannot escape.…

springboot整合返回数据统一封装

1、MagCode&#xff0c;错误码枚举类 package com.mgx.common.enums;import lombok.*; import lombok.extern.slf4j.Slf4j;/*** 错误码* author mgx*/ Slf4j NoArgsConstructor AllArgsConstructor public enum MsgCode {/*** 枚举标识&#xff0c;根据业务类型进行添加*/Code…

ClickHouse进阶(十八):clickhouse管理与运维-用户配置

进入正文前&#xff0c;感谢宝子们订阅专题、点赞、评论、收藏&#xff01;关注IT贫道&#xff0c;获取高质量博客内容&#xff01; &#x1f3e1;个人主页&#xff1a;含各种IT体系技术,IT贫道_大数据OLAP体系技术栈,Apache Doris,Kerberos安全认证-CSDN博客 &#x1f4cc;订阅…

ABB机器人如何修改num数据类型的参数?

ABB机器人如何修改num数据类型的参数? 在实际的生产项目中,机器人中可能会声明一些num数据类型的变量,作为相关的生产参数,例如:生产计数、等待时间、吹气时间、电磁阀动作时间等, 那么,如何在必要时对这些参数进行修改呢? 具体的方法和步骤可参考以下内容: 如下图所示…

《金字塔原理》阅读笔记

我们都希望在思考、沟通交流和解决问题时&#xff0c;重点突出&#xff0c;思路清晰&#xff0c;层次分明。我们评价人时&#xff0c;有一个标准是逻辑思维能力&#xff0c;而逻辑思维能力的标准又是什么&#xff1f;我们指导别人“要逻辑清晰、条理分明”&#xff0c;可怎样才…

JavaWeb 学习笔记 3:Servlet

JavaWeb 学习笔记 3&#xff1a;Servlet 1.简介 Servlet 是 JavaEE 定义的一套 Web 应用开发标准&#xff08;接口&#xff09;&#xff0c;实现了该技术的 Web 服务器软件&#xff08;如 Tomcat&#xff09;上可以运行一个 Servlet 容器&#xff0c;只要我们使用 Servlet 技…

【Kubernetes二进制安装】

Kubernetes二进制安装 cluster-health&#xff1a;检查etcd集群的运行状况也就是说 kubelet 首次访问 API Server 时&#xff0c;是使用 token 做认证&#xff0c;通过后&#xff0c;Controller Manager 会为 kubelet 生成一个证书&#xff0c;以后的访问都是用证书做认证了。在…

RS485以及MODBUS学习

学习目的&#xff1a; 1、什么是485&#xff1f; 2、485如何通信&#xff1f; 3、如何使用熟能生巧&#xff1f; RS485是一种四总线通信&#xff0c;分别是VCC、GND、485_A、485_B。两根负责通信&#xff0c;两根负责进行供电。 RS485通信 硬件层&#xff1a;解决的是数据传输问…

【ELFK】之消息队列kafka

一、kafka的定义 Kafka 是一个分布式的基于发布/订阅模式的消息队列&#xff08;MQ&#xff0c;Message Queue&#xff09;&#xff0c;主要应用于大数据实时处理领域。Kafka 是最初由 Linkedin 公司开发&#xff0c;是一个分布式、支持分区的&#xff08;partition&#xff0…

Arduino程序设计(十)8×8 LED点阵显示(MAX7219)

88 LED点阵显示 前言一、MAX7219点阵模块二、点阵显示实验1、点阵显示部分图形2、点阵显示数字 0 ~ 9 及 26 个英文字母 总结 前言 本文主要介绍88 LED点阵显示实验&#xff0c;分别是&#xff1a;1、介绍MAX7219点阵模块&#xff1b;2、点阵显示部分图形&#xff1b;3、点阵显…

探索以太坊 Layer 2 解决方案的后起之秀——Starknet

作者: stellafootprint.network 数据来源: Starknet Dashboard “区块链三难题”&#xff0c;或“可扩展性三难题”&#xff0c;强调了区块链平台想要去平衡安全性、去中心化和可扩展性将面临的挑战。通常情况下&#xff0c;区块链架构只能有效地优先考虑其中两个难题。例如&…

蓝牙核心规范(V5.4)10.2-BLE 入门笔记之CIS篇

LE CIS 同步通信 同步通信提供了一种使用蓝牙LE在设备之间传输有时间限制的数据的方式。它提供了一个机制,允许多个接收器设备在不同的时间从相同的源接收数据,以同步它们对该数据的处理。LE AUDIO使用同步通信。 当使用同步通信时,数据具有有限的时间有效期,在到期时被认…