当前位置: 首页 > news >正文

【C语言进阶】动态内存管理

在这里插入图片描述

👦个人主页:@Weraphael
✍🏻作者简介:目前是C语言学习者
✈️专栏:C语言航路
🐋 希望大家多多支持,咱一起进步!😁
如果文章对你有帮助的话
欢迎 评论💬 点赞👍🏻 收藏 📂 加关注


目录

  • 一、动态内存分配的由来
  • 二、动态内存函数的介绍
      • 2.1 malloc函数
      • 2.2 free函数
      • 2.3 calloc函数
      • 2.4 realloc函数
  • 三、常见的动态内存错误
      • 3.1 对NULL指针的解引用操作
      • 3.2 对动态开辟空间的越界访问
      • 3.3 对非动态开辟内存使用free释放
      • 3.4 使用free释放一块动态开辟内存的一部分
      • 3.5 对同一块动态内存多次释放
      • 3.6 动态开辟内存忘记释放

一、动态内存分配的由来

我们已经张伟的内存开辟方式有:

int a = 3;//在内存空间开辟4个字节
char a[10] = {0};//在内存开辟10个字节且连续的空间

但是上述的开辟空间的方式有两个特点:

  1. 空间开辟大小是固定
  2. 数组再声明的时候,必须指定数组的长度,它所需要的内存在编译时分配。

但是对于空间的需求,不仅仅是上述的情况。因为有时候我们需要的空间大小在程序运行的时候才知道,那么以上的方式就不能满足了。而动态内存分配恰好能在需要时随时开辟,不需要的时候随时释放,且分配的大小就是程序要求的大小

二、动态内存函数的介绍

2.1 malloc函数

在这里插入图片描述

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

  • 如果开辟成功,则返回一个指向开辟好的空间的指针
  • 如果开辟失败,则返回一个NULL指针(空指针),因此malloc函数的返回值一定要做检查
    *返回值是void*,表示的是无具体类型的指针,这说明malloc函数并不知道开辟空间的类型,具体是在使用的时候让使用者来决定
  • 如果参数size为0,malloc的行为是标准未定义的,取决用编译器

malloc函数实例】

strerror讲解传送门 -> 点击此处

#include <stdio.h>
#include <stdlib.h> //malloc函数所需头文件
#include <errno.h>  //errno所需头文件
#include <string.h>//strerror所需头文件int main()
{//假设向内存申请40个字节,用来存放整型int* p = (int*)malloc(40);//判断返回值是否为空指针if (p == NULL){//说明开辟内存空间失败了,那就显示为什么失败了printf("%s\n", strerror(errno));return 1;}//否则返回值就不为空指针//假设存放数据1~10for (int i = 0; i < 10; i++){*(p + i) = 1 + i;}//打印for (int i = 0; i < 10; i++){printf("%d ", *(p + i));}return 0;
}

在这里插入图片描述

2.2 free函数

malloc函数实例中,代码会存在隐患。malloc函数既然在内存中申请了空间,用完了就应该还给操作系统。所以C语言提供了另外一个函数free专门用做动态内存的释放和回收的

在这里插入图片描述

解读:

  • free函数是用来释放内存块
  • free函数无返回值
  • 参数ptr是指向先前使用 malloc、calloc 或 realloc 分配的内存块的指针。
  • 如果参数ptr指向的空间不是动态开辟的,那么free函数的行为就是未定义的
  • 如果参数ptrNULL指针,则函数不会做任何事。

free函数实例(完善malloc函数实例)】

#include <stdio.h>
#include <stdlib.h> //malloc函数所需头文件
#include <errno.h>  //errno所需头文件
#include <string.h>//strerror所需头文件int main()
{//假设向内存申请40个字节,用来存放整型int* p = (int*)malloc(40);//判断返回值是否为空指针if (p == NULL){//说明开辟内存空间失败了,那就显示为什么失败了printf("%s\n", strerror(errno));return 1;}//否则返回值就不为空指针//假设存放数据1~10for (int i = 0; i < 10; i++){*(p + i) = 1 + i;}//打印for (int i = 0; i < 10; i++){printf("%d ", *(p + i));}//释放申请的内存free(p);p = NULL;return 0;
}

释放完空间后,p = NULL的原因:
我们可以通过F10调试来观察
释放前:我们将数据1~10存放到内存了
在这里插入图片描述

释放后:我们发现,p在释放后还指向释放前的空间

在这里插入图片描述
所以,为了防止日后非法访问,我们就将p=NULL

2.3 calloc函数

C语言还提供一个函数calloccalloc函数也用来动态内存分配

在这里插入图片描述

解读:

  • 参数num是开辟元素的个数
  • 参数size是每个元素的大小
  • callocmalloc区别在于calloc会在返回地址之前把申请的空间的每个字节初始化为0

【calloc函数实例】

calloc会将申请的空间全部初始化为0

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>int main()
{//向内存申请10个元素,每个元素都是int类型int* p = calloc(10, sizeof(int));//判断p是否为空指针if (p == NULL){printf("%s\n", strerror(errno));return 1;}//否则不是空指针for (int i = 0; i < 10; i++){printf("%d ", *(p + i));}//用完释放空间freefree(p);p = NULL;return 0;
}

在这里插入图片描述

2.4 realloc函数

  • realloc函数的出现让动态内存管理更加灵活
  • 有时候会发现过去申请的空间太小了,有时候又会觉得申请的空间过大,那为了合理的使用内存,就要对内存的大小做灵活的调整。使用realloc函数就的功能就是调整动态开辟内存大小

在这里插入图片描述

解读:

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

realloc函数在调整内存空间的时候存在两种情况:

  1. 当原有空间之后有足够大的空间,要扩展内存就直接在原有内存之后直接追加空间,原来空间的数据不发生变化,返回的是原来的地址
  2. 当原有空间之后没有足够大的空间,扩展的方法:在堆空间上另找一个合适大小的连续空间来使用。这样函数返回的是一个新内存的地址

【realloc函数实例】

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>int main()
{//假设向内存申请20个字节来存放5个整型int* p = (int*)malloc(20);//判断p是否为空指针if (p == NULL){printf("%s\n", strerror(errno));return 1;}//否则p就不是空指针//接下来就将5个整型全部赋值成1for (int i = 0; i < 5; i++){*(p + i) = 1;}//那么接下来假设我还要再开辟5个空间(realloc)int* ptr = (int*)realloc(p, 40);if (ptr != NULL)//说明扩容成功{p = ptr;}//打印10个整型for (int i = 0; i < 10; i++){printf("%d ", *(p + i));}//释放空间(free)free(p);p = NULL;return 0;
}

在这里插入图片描述

三、常见的动态内存错误

3.1 对NULL指针的解引用操作

#include <stdio.h>
#include <stdlib.h>int main()
{int* p = (int*)malloc(40);*p = 20;free(p);p = NULL;return 0;
}
  • p = NULL,对于空指针解引用可能会导致程序异常终止或拒绝服务。

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

#include <stdio.h>
#include <stdlib.h>int main()
{//向内存申请10个整型的空间int* p = (int*)malloc(10 * sizeof(int));if (p == NULL){return 1;}for (int i = 0; i <= 10; i++){*(p + i) = i;}free(p);p = NULL;return 0;
}
  • 当指针指向的范围超过数组的范围时,p就是野指针,而野指针是没有访问权限的地址,会造成非法访问

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

#include <stdio.h>
#include <stdlib.h>int main()
{int a = 10;int* p = &a;free(p);p = NULL;return 0;
}
  • 这个就是free函数的概念,free的参数指向的空间一定是动态开辟的,比如:mallocrealloccalloc。而这里的p指向的是一个变量的地址

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

#include <stdio.h>
#include <stdlib.h>int main()
{int* p = (int*)malloc(40);p++;free(p);p = NULL;return 0;
}
  • 要知道不管是前置++还是后置++,它都是会有副作用的。p++后,p就会指向p++的位置,然后使用free释放只会释放p后面的内存空间,只释放了一部分
    在这里插入图片描述

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

#include <stdio.h>
#include <stdlib.h>int main()
{int* p = (int*)malloc(40);if (p == NULL){return 1;}free(p);free(p);return 0;
}
  • 对一次free回收了p申请的内存空间,此时的p就是野指针,而野指针是没有访问地址的权限,若再一次使用free来回收内存空间,可能会造成非法访问

3.6 动态开辟内存忘记释放

#include <stdio.h>
#include <stdlib.h>int main()
{int* p = (int*)malloc(40);if (p == NULL){return 1;}*p = 20;return 0;
}
  • 使用完内存空间后,并没有释放(free)内存空间,会导致内存泄漏

相关文章:

【C语言进阶】动态内存管理

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前是C语言学习者 ✈️专栏&#xff1a;C语言航路 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac; 点赞&a…...

第一批因ChatGPT坐牢的人,已经上路了

大家好&#xff0c;我是 Jack。 ChatGPT 的火爆有目共睹&#xff0c;有人靠着它赚了第一桶金&#xff0c;也有人靠着它即将吃上第一顿牢饭。 任何一件东西的火爆&#xff0c;总会给一些聪明人带来机会。 艾尔登法环火的时候&#xff0c;一堆淘宝卖魂的&#xff1b;羊了个羊火…...

Eclipse下Maven的集成

Eclipse下Maven的集成 2.1指定本地maven环境 参考&#xff1a;Eclipse的Maven创建_叶书文的博客-CSDN博客_eclipse创建maven项目 指定用本地maven指定maven仓库设置和地址2.2创建maven项目 1.新建 2.目录设置 3.坐标设置&#xff08;随便写就行&#xff09; 4.目录结构 2.3配置…...

Elasticsearch7学习笔记(尚硅谷)

文章目录一、ElasticSearch概述1、ElasticSearch是什么2、全文搜索引擎3、ElasticSearch 和 Solr3.1 概述3.2 比较总结二、Elasticsearch入门1、Elasticsearch安装1.1 下载使用1.2 数据格式2、索引操作3、文档操作&#xff08;了解&#xff09;3.1 创建文档3.2 文档查询3.3 文档…...

前端学习第一阶段-第7章 品优购电商项目

7-1 品优购项目介绍及准备工作 01-品优购项目导读 02-网站制作流程 03-品优购项目规划 04-品优购项目搭建 05-品优购项目-样式的模块化开发 06-品优购项目-favicon图标制作 07-品优购项目-TDK三大标签SEO优化 7-2 首页Header区域实现 08-品优购首页-快捷导航shortcut结构搭建 0…...

cocos2dx 4.0 - cpp - pc版 环境搭建

开发环境vs2022 cocos2dx4.0 python2.7.18 cmake3.25安装教程&#xff08;环境搭建&#xff09;安装VS2022-Community&#xff0c; 勾选c进行安装安装cmake3.25, 勾选环境变量进行安装安装python2.7.18, 勾选环境变量进行安装下载cocos2dx4.0并解压配置cocos2dx:运行cmd,进入…...

剑指 Offer 53 - I. 在排序数组中查找数字 I

原题链接 难度&#xff1a;easy\color{Green}{easy}easy 题目描述 统计一个数字在排序数组中出现的次数。 示例 1: 输入: nums [5,7,7,8,8,10], target 8 输出: 2示例 2: 输入: nums [5,7,7,8,8,10], target 6 输出: 0提示&#xff1a; 0<nums.length<1050 <…...

华为OD机试 - 删除指定目录(Python) | 机试题算法思路 【2023】

最近更新的博客 华为OD机试 - 热点网络统计 | 备考思路,刷题要点,答疑 【新解法】 华为OD机试 - 查找单入口空闲区域 | 备考思路,刷题要点,答疑 【新解法】 华为OD机试 - 好朋友 | 备考思路,刷题要点,答疑 【新解法】 华为OD机试 - 找出同班小朋友 | 备考思路,刷题要点…...

PowerShell Install Office 2021 Pro Plus Viso Professional

前言 微软Office在很长一段时间内都是最常用和最受欢迎的软件。从小型创业公司到大公司,它的使用比例相当。它可以很容易地从微软的官方网站下载。但是,微软只提供安装程序,而不提供完整的软件供下载。这些安装文件通常比较小。下载并运行后,安装的文件将从后端服务器安装M…...

KubeSphere实战

文章目录一、KubeSphere平台安装1、Kubernetes上安装KubeSphere1.1 安装docker1.2 安装Kubernetes1.3 前置环境之nfs存储1.4 前置环境之metrics-server1.5 安装KubeSphere2、Linux单节点部署KubeSphere3、Linux多节点部署KubeSphere(推荐)二、KubeSphere实战1、多租户实战2、中…...

Linux 简介

Linux 内核最初只是由芬兰人林纳斯托瓦兹&#xff08;Linus Torvalds&#xff09;在赫尔辛基大学上学时出于个人爱好而编写的。 Linux 是一套免费使用和自由传播的类 Unix 操作系统&#xff0c;是一个基于 POSIX 和 UNIX 的多用户、多任务、支持多线程和多 CPU 的操作系统。 …...

java面试题-泛型异常反射

泛型1.什么是泛型&#xff1f;Java是一种强类型语言&#xff0c;数据类型在编译时必须确定。如果我们想要在代码中使用不同类型的数据&#xff0c;那么就需要为每种类型分别写出相应的代码。这样会导致代码冗长、重复&#xff0c;也不便于维护。为了解决这个问题&#xff0c;Ja…...

详细解读ChatGPT:如何调用ChatGPT的API接口到官方例子的说明以及GitHub上的源码应用和csdn集成的ChatGPT

文章目录1. 解读ChatGPT1.1 词语解释1.2 功能解读2. GitHub上ChatGPT的应用源码3. 调用ChatGPT的API4. 官方例子说明5. 集成ChatGPT自ChatGPT出来到如今&#xff0c;始终走在火热的道路上&#xff0c;如今日活用户破亿&#xff0c;他为何有如此大的魅力&#xff0c;深受广大用户…...

九龙证券|最新评级情况出炉,机构扎堆这一板块!聚氨酯龙头获得最多关注

本周算计254家上市公司获组织“买入型”评级。 电子板块评级组织扎堆 证券时报数据宝计算&#xff0c;2月13日至17日&#xff0c;A股市场53家组织算计进行347次评级&#xff0c;254家上市公司获“买入型”评级&#xff08;包含买入、增持、强烈推荐、推荐&#xff09;。 从申…...

考研复试机试 | C++ | 尽量不要用python,很多学校不支持

目录1.1打印日期 &#xff08;清华大学上机题&#xff09;题目&#xff1a;代码&#xff1a;1.2改一改&#xff1a;上一题反过来问题代码&#xff1a;2.Day of Week &#xff08;上交&&清华机试题&#xff09;题目&#xff1a;代码&#xff1a;3.剩下的树&#xff08;清…...

ChatGPT时代,别再折腾孩子了

今天这篇完全是从两件事儿有感而发。昨天在文印店&#xff0c;在复印机上看到装订好的几页纸&#xff0c;我瞥了一眼&#xff0c;是历史知识点&#xff1a;隋朝大运河分为四段&#xff0c;分别是___ ___ ___ ___&#xff0c;连接了五大河___ ___ ___ ___ ______ 年&#xff…...

万字干货 | 荔枝魔方基于云原生的架构设计与实践

近年来&#xff0c;荔枝集团在国内和海外的业务迅速发展&#xff0c;业务数据规模也是成几何式地增长&#xff0c;海量数据的计算分析场景、业务智能算法应用需求随之而生&#xff0c;为了快速地满足业务发展的需要&#xff0c;我们面临着诸多的技术挑战。技术挑战工程问题资源…...

#科研筑基# python初学自用笔记 第九篇 面向对象编程

面向对象编程 Object Oriented Programming &#xff0c;简称OOP&#xff0c;是一种程序设计思想&#xff0c;这种思想把对象作为程序的基本单元。类是抽象的&#xff0c;对象是具体的&#xff0c;一种类包括其特定的数据或属性&#xff0c;以及操作数据的函数&#xff08;方法…...

Python快速上手系列--邮件发送--详解篇

本章就来一起学习一下跑完自动化脚本后如何自动的发送邮件到指定的邮箱。zmail操作&#xff1a;1. 导包 import zmail2. 邮件内容&#xff0c;包含&#xff1a;主题(subject)、正文(content_text)、附件(attachments)3. 发件人信息&#xff0c;包含&#xff1a;发件人账号&…...

【Bluetooth开发】蓝牙开发入门

BLE 蓝牙设备在生活中无处不在&#xff0c;但是我们也只是将其作为蓝牙模块进行使用&#xff0c;发送简单的AT命令实现数据收发。 那么&#xff0c;像对于一些复杂的使用场合&#xff1a;“车载蓝牙”、"智能手表"、“蓝牙音箱”等&#xff0c;我们不得不去了解底层…...

07:进阶篇 - 在程序中嵌入 CTK Plugin Framework

作者: 一去、二三里 个人微信号: iwaleon 微信公众号: 高效程序员 如果已经创建了一个应用程序,现在要将 CTK Plugin Framework 嵌入其中,该如何进行呢? 下面,以《06:进阶篇 - Hello,CTK!》中的插件为例,来演示如何使用 CTK Plugin Framework 来加载插件并获取特定…...

快速低成本动画视频课

快速低成本动画视频课Character Animator能做什么如何用character animator制作动画视频Animate能做什么Adobe Animate和Character Animator结合&#xff0c;如何快速制作低成本动画视频课Character Animator能做什么 Character Animator是Adobe公司的一个动画制作软件&#x…...

大数据平台测试-软件测试常见面试回答(持续更新)

面试造航母&#xff0c;入职拧螺丝。面试&#xff0c;讲点面试官想听的。。。 1、你有过漏测的经历吗&#xff1f; 答&#xff1a;这道题肯定是回答有。然后展开描述。就类似面试官问 你印象比较深的一个bug。。。 测试无穷尽&#xff0c;质量也并非测试一个岗位的责任&…...

链表学习之反转链表

链表解题技巧 额外的数据结构&#xff08;哈希表&#xff09;&#xff1b;快慢指针&#xff1b;虚拟头节点&#xff1b; 反转链表 分别实现单向链表和双向链表的反转。 要求&#xff1a;长度为N的链表&#xff0c;时间复杂度为O(N)&#xff0c;额外空间复杂度为O(1)。 反转…...

ONNXRUNTUIME实例分割网络说明

ONNXRUNTUIME c使用&#xff08;分割网络&#xff09;与相关资料&#xff08;暂记&#xff09; initiate a env with an id name(使用id名称启动env) create session (创建会话 ) onnxenv -> sessioninputname [“x”] ,outputname [“t”]inputnodedim [[1,1,192,192…...

几行代码,就写完懒加载啦?

Ⅰ、前言 「懒加载」是网页中非常 常见的&#xff1b;为了减少系统的压力&#xff0c;对于一些电商系统出场频率非常高&#xff1b;那么大家一般用什么方式去实现 「懒加载」 呢 &#xff1f; ① 通过 scroll 的形式&#xff1a; 通过 滚动「scroll」事件&#xff0c;然后去判…...

PyTorch常用的损失函数(ChatGPT)

L1Loss nn.L1Loss 也称为平均绝对误差&#xff08;Mean Absolute Error&#xff0c;MAE&#xff09;。它计算预测值与真实值之间的差异&#xff08;即误差&#xff09;&#xff0c;然后取绝对值并求和&#xff0c;最后除以样本数量得到平均误差。具体来说&#xff0c;对于一批…...

LeetCode——1237. 找出给定方程的正整数解

一、题目 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;https://leetcode.cn/problems/find-positive-integer-solution-for-a-given-equation/description/ 翻译一下题目 意思是&#xff0c;这是一个二维单调递增的函数&#xff0c;函数一共有 9 …...

系统编程中的进程的概念No.3【进程状态】

引言&#xff1a; 北京时间&#xff1a;2023/2/17/8:17&#xff0c;目前听着超能陆战队主题曲《Immortals》&#xff0c;感觉又要螺旋式升天&#xff0c;并且为我今天上午没课感到happy&#xff0c;所以继我们很久以前的关于进程的博客&#xff0c;今天我们就再来学习一下有关…...

推荐 3 款 Golang 语义化版本库

文章目录1.什么是语义化版本 2.0.02.Golang 语义化版本库比较3.小结参考文献1.什么是语义化版本 2.0.0 语义化版本 2.0.0&#xff08;Semantic Versioning 2.0.0&#xff09;是一种用于标识软件版本的约定和规范。它包含三个数字组成的版本号&#xff0c;格式为“MAJOR.MINOR.…...

山西众邦建设集团网站/万能浏览器

一、快速访问 在企业环境中&#xff0c;用户数量比较多&#xff0c;文件数据的存放也是很无常的&#xff0c;不管我们是从本地、共享、还是云端&#xff0c;我们都会面临到一个问题&#xff0c;想要快读访问我们的文件&#xff0c;已经越来越困难了。这是因为我们的文件由于公司…...

wordpress 页面内分页/谷歌chrome

目录 进程概念 进程的特征 进程状态 进程控制块 进程概念 是程序的一次执行过程&#xff0c;是系统进行资源分配和处理机调度的一个独立单位。 是一个运行中程序的描述&#xff0c;通过描述信息中的内存指针可以找到内存中运行的程序代码及数据&#xff0c;并且通过上下文…...

个人网站做什么类型的/百度上海分公司地址

如果我们的电脑上存储了不少重要的资料文件&#xff0c;为了防止别人插入移动设备&#xff08;比如U盘或者移动硬盘等&#xff09;&#xff0c;比较笨的方法就是将USB接口堵住&#xff0c;其实我们只需要在电脑中设置一下&#xff0c;我们就可以让别人U盘或移动硬盘无法复制拷贝…...

2021网站你懂我意思正能量/最好的网络营销软件

作为Java程序员来说&#xff0c;最痛苦的事情莫过于可以选择的范围太广&#xff0c;可以读的书太多&#xff0c;往往容易无所适从。首先列举一份比较热门的&#xff0c;也就是大家都在看的。 首先看看哪些书卖得比较多 这是一份来自北京新华书店实际销售榜上的图书&#xff0…...

常见网站结构有哪些/优化seo报价

1&#xff1a;首先去官网下载安装包 下载地址&#xff1a;https://dev.mysql.com/downloads/mysql/ 2&#xff1a;将解压文件解压到你安装的目录&#xff1a;C:\mysql-8.0.20-winx64 &#xff08;不要放在有中文名字和空格的的目录下&#xff09; 3&#xff1a;在C:\mysql-8…...

wordpress需要做哪些设置/网络公司名字大全

HSTS(HTTP Strict Transport Security) 简单来说就是由浏览器进行http向https的重定向。如果不使用HSTS&#xff0c;当用户在浏览器中输入网址时没有加https&#xff0c;浏览器会默认使用http访问&#xff0c;所以对于https站点&#xff0c;通常会在服务端进行http至https的重定…...