C 学习笔记 —— 动态分配内存(malloc)
文章目录
- 分配内存
- malloc
- calloc
- realloc
- 创建数组方式
- free的重要性
- 举例
- 常见动态分配内存错误
- 忘记检查所请求的内存
- 对NULL指针进行解引用
- 对分配的内存越界访问
- 释放一块内存后,继续使用
- 释放一块内存的一部分是不允许的
- 内存泄漏
分配内存
当一个数组声明时,需要指定数组大小,这个内存空间在编译的时候就已经被分配了。
但是如果我们要使用一个数组,我们事先并不知道他的大小,而想在运行时计算出来,那么也可以在程序运行时动态分配内存。
上面的内存分配与回收都是系统帮我们做了,而我们不用管。如果我们想自己更灵活的分配和回收内存可以使用malloc和free。
需要引入#include <stdlib.h>库头文件,内存分配函数在这里面。
malloc
void * malloc(size_t size);
给malloc一个参数,表示要申请的内存大小,所需的byte数。
malloc会在内存池中找到一块空闲(连续)内存,返回内存块的首字节地址,所以可以把该地址赋值给一个指针,后面可以使用该指针访问这块内存。
这块内存通常比malloc申请的大一些,因为要存储一些信息。
如果malloc分配内存失败,则他会返回一个空指针 NULL,我们可以通过是否为空指针来判断是否成功分配了内存,这个很重要。
返回值类型是一个void类型的指针,该类型相当于一个通用指针,该指针通常被强转为一个匹配的类型并不需要考虑类型不匹配的问题,并且我们应该坚持这样做来保证代码的可读性,C中虽然不要求强制转换,但是C++中必须使用,那么我们坚持这样做来保证可移植性。
double *pt = (double *) malloc (30 * sizeof(double));
这段代码为30个double类型的值申请了一块内存,并设置pt指向该内存首元素地址。
回忆一下,数组名为该数组的首元素地址。所以pt指向该块内存的首元素,那么我们可以用数组名来使用它。可以使用数组名来表示指针,也可以使用指针来表示数组名。
我们可以使用pt[0]来访问该块的首元素,pt[1]来访问第二个元素。
calloc
函数原型
void * calloc(size_t num_elements, size_t element_size);
calloc函数
long* num;
num = (long *)calloc(100, sizeof(long));
calloc第一个参数是存储单元数量,第二个参数是存储单元大小。
他的返回值也是void* 需要强转成需要的类型。
他还有一个特性是会把分配后的所有值都初始化为0. malloc不保证这一点,他的内存值并没有初始化为0。
realloc
void *realloc(void *ptr, size_t new_size);
realloc函数用于修改一个原先已经分配的内存块的大小。
使用这个函数可以让一个内存扩大或者缩小。
如果扩大内存,则原内容保留,扩大到内存部分并不保证数据的初始化。
如果缩小内存,则改内存尾部部分会被删掉 ,剩余内存保留原县内容。
操作系统中可能原内存块无法改变大小,这是操作系统会分配一块新内存出来,新内存遵循上面两个规则,并将新指针返回。
如果realloc的第一个参数为NULL,则他的行为和malloc函数一摸一样。
创建数组方式
所以现在我们有两种方式创建数组
第一种:直接创建double item[30];
第二种:动态创建
int n = 6;
double *pt = (double *) malloc(n * sizeof(double));
第一种我们必须指定一个常量作为数组的大小。
而第二种的优势是我们可以创建一个变长数组。
使用malloc在运行时才确定内存数组的大小。
使用的时候,我们不仅可以使用指针,还可以使用下标来访问内存,如下例子:
#include <stdio.h>
#include <stdlib.h> /* for malloc(), free() */int main(void)
{double * ptd;int max;int number;int i = 0;max = 6;ptd = (double *) malloc(max * sizeof (double)); //分配动态数组if (ptd == NULL) //如果分配失败则退出{puts("Memory allocation failed. Goodbye.");exit(EXIT_FAILURE);//异常退出程序}/* ptd now points to an array of max elements */puts("Enter the values (q to quit):");while (i < max && scanf("%lf", &ptd[i]) == 1)++i;printf("Here are your %d entries:\n", number = i);for (i = 0; i < number; i++){printf("%7.2f ", ptd[i]); //使用指针也即数组名访问元素if (i % 7 == 6)putchar('\n');}if (i % 7 != 0)putchar('\n');puts("Done.");free(ptd);//释放内存return 0;
}
free的重要性
我们使用free函数来释放malloc分配的内存,free接受参数为malloc返回的指针。
free的参数要么是NULL,要么是malloc,calloc,realloc返回的值。
当不断分配内存而忘记释放,可能会耗尽内存,这类问题称为内存泄漏。
举例
#include <stdio.h>
#include <stdlib.h>
#include <string.h>int static_store = 30;
const char * pcg = "String Literal";
int main()
{int auto_store = 40;char auto_string[] = "Auto char Array";int * pi;char * pcl;pi = (int *) malloc(sizeof(int));*pi = 35;pcl = (char *) malloc(strlen("Dynamic String") + 1);strcpy(pcl, "Dynamic String");printf("static_store: %d at %p\n", static_store, &static_store);printf(" auto_store: %d at %p\n", auto_store, &auto_store);printf(" *pi: %d at %p\n", *pi, pi);printf(" %s at %p\n", pcg, pcg);printf(" %s at %p\n", auto_string, auto_string);printf(" %s at %p\n", pcl, pcl);printf(" %s at %p\n", "Quoted String", "Quoted String");free(pi);free(pcl);return 0;
}
// static_store: 30 at 0x601048 静态区域
// auto_store: 40 at 0x7fff5f25f8dc 自动区域
// *pi: 35 at 0xeea010 堆
// String Literal at 0x4007a0 静态区域
// Auto char Array at 0x7fff5f25f8c0 自动区域
// Dynamic String at 0xeea030 堆
// Quoted String at 0x40080e 静态区域
常见动态分配内存错误
忘记检查所请求的内存
对NULL指针进行解引用
对分配的内存越界访问
如果我们通过数组下标访问了arr[-1]或者arr[11],那么arr[-1]是向前越界了,arr[11]是向后越界了。一般越界是越到变量分配的内存区域的后面区域,很少越界到当前访问的变量内存前面去的。有人可能会说,怎么可能会越界到负的下标(arr[-1])上去了呢?我们还真遇到过,后面我们给大家专门讲一个向前越界的实例。
释放一块内存后,继续使用
释放一块内存的一部分是不允许的
free(pi+5)
内存泄漏
相关文章:
C 学习笔记 —— 动态分配内存(malloc)
文章目录分配内存malloccallocrealloc创建数组方式free的重要性举例常见动态分配内存错误忘记检查所请求的内存对NULL指针进行解引用对分配的内存越界访问释放一块内存后,继续使用释放一块内存的一部分是不允许的内存泄漏分配内存 当一个数组声明时,需要…...
RK3588通用布线设计指南
(1)走线长度应包含过孔和封装。(2)由于表贴器件的焊盘会导致阻抗降低,为减小阻抗突变的影响,建议在表贴焊盘的正下方按焊盘大小挖去一层参考层。常用的表贴器件有:电容、 ESD、共模抑制电感、连…...
ChatGPT也懂如何设计开发板!?
到底应该如何设计一款开发板?我们问了一下最近风很大的ChatGPT,得出了这样的回答: 或者这样的回答: 显而易见,RK3568开发板是一款功能丰富,性能优异,易于开发的高性能开发板,适用于各…...
去了字节跳动,才知道年薪40W的测试居然有这么多?
今年大环境不好,内卷的厉害,薪资待遇好的工作机会更是难得。最近脉脉职言区有一条讨论火了: 哪家互联网公司薪资最‘厉害’? 下面的评论多为字节跳动,还炸出了很多年薪40W的测试工程师 我只想问一句,现在的…...
2023前端面试知识点总结
原型 JavaScript中的对象都有一个特殊的 prototype 内置属性,其实就是对其他对象的引用 几乎所有的对象在创建时 prototype 属性都会被赋予一个非空的值,我们可以把这个属性当作一个备用的仓库 当试图引用对象的属性时会出发get操作,第一步时…...
FL StudioV21电脑版水果编曲音乐编辑软件
这是一款功能十分丰富和强大的音乐编辑软件,能够帮助用户进行编曲、剪辑、录音、混音等操作,让用户能够全面地调整音频。FL水果最新版是一款专业级别的音乐编曲软件,集合更多的编曲功能为一身,可以进行录音、编辑、制作、混音、调…...
【数据结构初阶】实现顺序表的简单功能
目录一.线性表和顺序表的概念二.顺序表的实现1.动态顺序表的创建2.初始化顺序表3.打印顺序表4.销毁顺序表5.检查容量6.头插 尾插7.头删 尾删三.使用下标插入删除1.删除指定位置2.向指定位置插入指定数一.线性表和顺序表的概念 线性表是n个具有相同特性的数据元素的有限序列。 线…...
华为OD机试题,用 Java 解【停车场车辆统计】问题
最近更新的博客 华为OD机试 - 猴子爬山 | 机试题算法思路 【2023】华为OD机试 - 分糖果(Java) | 机试题算法思路 【2023】华为OD机试 - 非严格递增连续数字序列 | 机试题算法思路 【2023】华为OD机试 - 消消乐游戏(Java) | 机试题算法思路 【2023】华为OD机试 - 组成最大数…...
Linux中使用Docker部署Mysql数据库
前言 和朋友一起搞一个项目,分了一下工作,但是mysql迟迟安装不上,程序都在一个环境里确实容易出现很多问题,浪费时间和经历在这些配置上,好在有docker了,就在docker里搭建一个Mysql数据库使用吧࿰…...
JPDA(远程调试)使用步骤
JPDA(Java Plateform Debugger Architecture) 更改启动脚本 vi catalina.sh 127行 CATALINA_OPTS “-Xdebug -Xrunjdwp:transportdt_socket,servery,suspendn,address5888” 指定端口,默认是8000 377行以jpda方式启动tomcat ./catalina.sh jpda start tomcat以这个…...
磷脂-聚乙二醇-丙烯酸酯;DSPE-PEG-AC试剂说明;DSPE-PEG-Acrylate科研用
中文名称:磷脂-聚乙二醇-丙烯酸酯 丙烯酸酯-聚乙二醇-磷脂 简称:DSPE-PEG-AC;DSPE-PEG-Acrylate 溶剂:溶于部分常规有机溶剂 PEG分子量:1000;2000;3400;5000等等 注意事项:避免…...
C++入门:异常处理
异常是程序在执行期间产生的问题。C 异常是指在程序运行时发生的特殊情况,比如尝试除以零的操作。异常提供了一种转移程序控制权的方式。C 异常处理涉及到三个关键字:try、catch、throw。throw: 当问题出现时,程序会抛出一个异常。这是通过使…...
C/C++每日一练(20230225)
目录 1. 工龄问题求解 ★ 2. 字符图形输出 ★★ 3. LRU 缓存机制 ★★★ 1. 工龄问题求解 给定公司N名员工的工龄,要求按工龄增序输出每个工龄段有多少员工。输入首先给出正整数N,即员工总人数; 随后给出N个整数,即每个员工…...
nyist最终淘汰赛第一场
我出的题喜欢吗 我要水题解所以每一篇题解都分一个博客 A 题解链接: Atcoder abc257 E_霾まる的博客-CSDN博客 构造贪心题 在本次淘汰赛中较难 B 题解链接: atcoder abc217 D_霾まる的博客-CSDN博客 STL二分题, 当然你可以数组二分, 相对麻烦一点 在本次淘汰赛中较简单…...
《零成本实现Web自动化测试--基于Selenium》 Selenium-RC
一. 简介 Selenium-RC可以适应更复杂的自动化测试需求,而不仅仅是简单的浏览器操作和线性执行。Selenium-RC能够充分利用编程语言来构建更复杂的自动化测试案例,例如读写文件、查询数据库和E-mail邮寄测试报告。 当测试案例遇到selenium-IDE不支持的逻辑…...
来阿里我的收获是什么?(未完待续)
不知不觉来阿里两年多了,每天都过的很充实,感觉这段时间没有学到什么东西,但是又觉得收获满满,恰好又好久没有动笔写过些什么了,所以有了这个动笔念头。 之前技术方面记录的比较多,这次就记录一些比较磨心的…...
golang net/http库的学习
net/http 是 Golang 标准库中用来构建 HTTP 服务器和客户端的包,它提供了很多功能强大的方法和接口,可以让您方便地构建和处理 HTTP 请求和响应。下面是一些学习 net/http 的建议: 了解 HTTP 协议。在学习 net/http 之前,建议先了…...
Spring(AOP)
目录 1. 预备知识-动态代理 1.1 什么是动态代理1.2 动态代理的优势1.3 基于JDK动态代理实现2. AOP 2.1 基本概念2.2 AOP带来的好处3. Spring AOP 3.1 前置通知3.2 后置通知3.3 环绕通知3.4 异常通知3.5 适配器 1. 预备知识-动态代理 1.1 什么是动态代理 动态代理利用Java的反…...
服务搭建篇(六) Kafka + Zookeeper集群搭建
一.Zookeeper 1.什么是Zookeeper ZooKeeper 是一个开源的分布式协调框架,是Apache Hadoop 的一个子项目,主要 用来解决分布式集群中应用系统的一致性问题。Zookeeper 的设计目标是将那些复杂且容 易出错的分布式一致性服务封装起来,构成一个…...
Go基础-可变参数函数
文章目录1 定义2 语法3 给可变函数参数传入切片4 修改可变参数函数中的切片1 定义 可变参数函数是一种参数个数可变的函数。 2 语法 语法 //关键字 函数名(参数1, elems为T类型的可变参数) 返回值类型 func name(params type, elems ...T) returntype{// 函数体 }…...
第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频
使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...
CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...
【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...
