C语言:动态内存管理

文章目录
- 一、动态内存函数
- 1. malloc
- 2. calloc
- 3. realloc
- 4. free
- 二、常见的错误
- 1.malloc或calloc开辟的空间未检查
- 2.越界访问
- 3.对非malloc和calloc开辟的空间,用free释放
- 4.对同一块动态内存多次释放
- 5.用free释放动态内存的一部分
- 三、通讯录(动态版本改写)
- 总结
一、动态内存函数
要介绍动态内存函数,我们就要知道动态内存函数开辟的空间在内存的什么位置。
如下图所示:

动态内存函数开辟的空间在堆区,该区域的空间,只有free函数和程序结束才会释放。
1. malloc
函数的声明:void* malloc (size_t size);包含在<stdlib.h>头文件中。
调用该函数可以向内存中申请大小为size个字节的连续空间,并返回该空间的起始地址。
注意:
- 如果malloc开辟空间成功,则返回成功开辟好空间的起始地址
- 如果malloc开辟空间失败,则返回NULL
- 不要开辟大小为0的空间,这是标准未定义的。
因此,malloc开辟空间后,我们要检查返回值。
#include <stdio.h>
#include <stdlib.h>int main()
{int* pa = (int*)malloc(sizeof(int) * 10);//开辟大小为40个字节的空间//检查是否空间开辟失败if (pa == NULL){exit(-1);}free(pa);pa = NULL;return 0;
}
2. calloc
函数的声明:void* calloc (size_t num, size_t size);包含在<stdlib.h>头文件中。
调用该函数可以向内存中申请num个大小是size个字节的连续空间,再将空间每一个字节初始化为0,并返回该空间的起始地址。
calloc与malloc的唯一区别在于,calloc会将空间每一个字节初始化为0。
如下所示:
#include <stdio.h>
#include <stdlib.h>int main()
{int* arr1 = (int*)malloc(sizeof(int) * 10);if (arr1 == NULL){exit(-1);}for (int i = 0; i < 10; i++){printf("%d ", arr1[i]);}printf("\n");int* arr2 = (int*)calloc(sizeof(int), 10);if (arr2 == NULL){exit(-1);}for (int i = 0; i < 10; i++){printf("%d ", arr2[i]);}free(arr1);free(arr2);arr1 = NULL;arr2 = NULL;return 0;
}

3. realloc
函数的声明:void* realloc (void* ptr, size_t size);包含在<stdlib.h>头文件中。
调用该函数可以调整由malloc和calloc开辟的空间大小,调整为size个字节大小的空间。
但要注意,其调整空间大小的方式有两种,原地扩容和异地扩容。
-
原地扩容,原地址空间后空间大小充足,在原地址空间直接扩容。
-
异地扩容,原地址空间后空间大小不够,在堆区另找一片充足的空间使用。
-
如果调整的大小过大,realloc会返回NULL。
//异地扩容
int main()
{int* pa = (int*)malloc(sizeof(int) * 10);if (pa == NULL){exit(-1);}printf("%p\n", pa);int* tmp = (int*)realloc(pa, sizeof(int) * 20);if (tmp != NULL){pa = tmp;printf("%p\n", pa);}free(pa);pa = NULL;return 0;
}

//原地扩容
int main()
{char* pa = (char*)malloc(sizeof(char) * 10);if (pa == NULL){exit(-1);}printf("%p\n", pa);char* tmp = (char*)realloc(pa, sizeof(char) * 20);if (tmp != NULL){pa = tmp;printf("%p\n", pa);}free(pa);pa = NULL;return 0;
}

4. free
函数的声明:void free (void* ptr);包含在<stdlib.h>头文件中。
调用该函数可以释放由malloc和calloc开辟的空间,指针变量ptr本身内容不变,需要程序员本身置空。
- 如果ptr是NULL,则函数什么事都不会做
- 如果ptr并不是malloc和calloc开辟的空间,那free函数的行为未定义
如下:
int main()
{int* pa = (int*)malloc(sizeof(int) * 10);if (pa == NULL){exit(-1);}free(pa);//释放pa所指向的空间pa = NULL;//pa置NULL,防止野指针return 0;
}
二、常见的错误
1.malloc或calloc开辟的空间未检查
有时开辟空间过大,而未检查时,会发生对NULL的解引用
int main()
{int* pa = (int*)malloc(sizeof(int) * INT_MAX);*pa = 10;free(pa);pa = NULL;return 0;
}

2.越界访问
访问超出开辟空间大小
int main()
{int* pa = (int*)malloc(sizeof(int) * 10);if (pa == NULL){exit(-1);}for (int i = 0; i < 11; i++){pa[i] = 0;}free(pa);pa = NULL;return 0;
}

3.对非malloc和calloc开辟的空间,用free释放
free函数只能用了释放动态内存空间
int main()
{int arr[10] = { 0 };free(arr);return 0;
}

4.对同一块动态内存多次释放
动态内存空间释放一次即可
int main()
{int* pa = (int*)malloc(sizeof(int) * 10);if (pa == NULL){exit(-1);}free(pa);free(pa);pa = NULL;return 0;
}

5.用free释放动态内存的一部分
开辟的动态内存空间实际大小要大于我们申请的大小,那多出的一部分空间要记录我们这次申请空间的信息,free函数就可以根据这一部分信息来释放我们申请的空间大小。如果我们传递的指针并未指向空间首地址,那么free就找不到信息来释放空间。
int main()
{int* pa = (int*)malloc(sizeof(int) * 10);if (pa == NULL){exit(-1);}pa++;free(pa);pa = NULL;return 0;
}

三、通讯录(动态版本改写)
静态版本通讯录
相对于静态版本而言,动态版本改变并不多也不难,下面就是要改变的部分。
- 结构
//动态版本
typedef struct Contact
{PeoInfo* data;int sz;//记录此时已用的大小int capacity;//记录通讯录的大小
}Contact;
2.初始化InitContact
#define INITSIZE 10//初始化通讯录
void InitContact(Contact* pc)
{pc->sz = 0;pc->capacity = INITSIZE;pc->data = (PeoInfo*)malloc(sizeof(PeoInfo) * INITSIZE);if (pc->data == NULL){perror("malloc");return;}
}
- 扩容AddCapacity
bool AddCapacity(Contact* pc)
{PeoInfo* tmp = realloc(pc->data, sizeof(PeoInfo) * (pc->capacity) * 2);if (tmp == NULL){perror("realloc");return false;}pc->data = tmp;pc->capacity *= 2;return true;
}//添加联系人
void AddContact(Contact* pc)
{assert(pc);if (pc->sz == pc->capacity){if (AddCapacity(pc) == true){printf("扩容成功\n");}else{printf("扩容失败\n");return;}}printf("请输入联系人名字:>");scanf("%s", pc->data[pc->sz].name);printf("请输入联系人性别:>");scanf("%s", pc->data[pc->sz].sex);printf("请输入联系人年龄:>");scanf("%d", &(pc->data[pc->sz].age));printf("请输入联系人电话:>");scanf("%s", pc->data[pc->sz].tele);printf("请输入联系人地址:>");scanf("%s", pc->data[pc->sz].adder);pc->sz += 1;
}
- 退出ExitContact
//退出通讯录
void ExitContact(Contact* pc)
{free(pc->data);pc->data = NULL;pc->sz = 0;pc->capacity = 0;
}
总结
以上就是我对于动态内存管理的了解和应用。
相关文章:
C语言:动态内存管理
文章目录 一、动态内存函数1. malloc2. calloc3. realloc4. free 二、常见的错误1.malloc或calloc开辟的空间未检查2.越界访问3.对非malloc和calloc开辟的空间,用free释放4.对同一块动态内存多次释放5.用free释放动态内存的一部分 三、通讯录(动态版本改写)总结 一、…...
如何往MySQL中插入100万条数据?
需求 现在有一个 数据量 为100万的数据样本 100w_data.sql 其数据格式如下,截取最后十条数据 999991,XxGdnLZObA999991,XxGdnLZObA,XxGdnLZObA,2020-3-18,1 999992,TBBchSKobC999992,TBBchSKobC,TBBchSKobC,2020-9-8,2 999993,rfwgLkYhUz999993,rfwgLkYhUz,rfwgLk…...
IntelliJ IDEA 2023.2 最新变化
主要更新 AI Assistant 限定访问 Ultimate 在此版本中,我们为 IntelliJ IDEA 引入了一项重要补充 – AI Assistant。 AI Assistant 当前具备一组由 AI 提供支持的初始功能,提供集成式 AI 聊天,可以完成一些任务,例如自动编写文档…...
1300*B. T-primes
解析: 有且只有三个因数,当且仅当,完全平方数并且sqrt(n)为素数 #include<bits/stdc.h> using namespace std; typedef long long ll; const int N1e55; ll t,n; bool prime(ll x){if(x<2) return 0;for(int…...
重新C++系列之运算符重载
一、什么是运算符重载 简单来讲就是对运算符赋予新的意义,但是又不能改变原有的含义,它本身也就是一个函数。运算符重载的本质是以函数的方式来体现。 二、运算符重载有几种 1、按照作用域来划分,有全局操作符重载函数和成员函数操作符重载函…...
kotlin异常处理try-catch-finally
kotlin异常处理try-catch-finally fun main(args: Array<String>) {try {println("a")} catch (e: Exception) {//异常捕获println("a-catch: $e")} finally {//善后,无论是否异常,都会执行println("a-finally")}t…...
Pytorch在cuda、AMD DirectML和AMD CPU下性能比较
一、测试环境 CUDA环境: i7-8550u 16G DDR4 2133MHz nVidia MX150 2GB AMD DirectML环境: Ryzen 5 5600G 32G DDR4 3200MHz Vega7 4GB AMD 纯CPU环境:Ryzen 5 5600G 32G DDR4 3200MHz 其他硬件配置的硬盘、电源均一致。Pytorch版本为2.0.0,Pyt…...
哈工大计算机网络课程局域网详解之:交换机概念
哈工大计算机网络课程局域网详解之:交换机概念 文章目录 哈工大计算机网络课程局域网详解之:交换机概念以太网交换机(switch)交换机:多端口间同时传输交换机转发表:交换表交换机:自学习交换机互…...
Jenkins Pipeline的hasProperty函数
函数的作用 用于判断某个参数或者字段是否存在。 用法 例子一 def projectStr "P1,P2,P3" pipeline {agent anyparameters {extendedChoice(defaultValue: "${projectStr}",description: 选择要发布的项目,multiSelectDelimiter: ,,name: SELECT_PROJ…...
芯片制造详解.净洁室的秘密.学习笔记(三)
这是芯片制造系列的第三期跟学up主三圈,这里对其视频内容做了一下整理和归纳,喜欢的可以看原视频。 芯片制造详解03: 洁净室的秘密|为何芯片厂缺人? 芯片制造详解.净洁室的秘密.学习笔记 三 简介一、干净的级别二、芯片…...
可解释的 AI:在transformer中可视化注意力
Visualizing Attention in Transformers | Generative AI (medium.com) 一、说明 在本文中,我们将探讨可视化变压器架构核心区别特征的最流行的工具之一:注意力机制。继续阅读以了解有关BertViz的更多信息,以及如何将此注意力可视化工具整合到…...
k8s Webhook 使用java springboot实现webhook 学习总结
k8s Webhook 使用java springboot实现webhook 学习总结 大纲 基础概念准入控制器(Admission Controllers)ValidatingWebhookConfiguration 与 MutatingWebhookConfiguration准入检查(AdmissionReview)使用Springboot实现k8s-Web…...
JS逆向之猿人学爬虫第20题-wasm
文章目录 题目地址sign参数分析python算法还原往期逆向文章推荐题目地址 https://match.yuanrenxue.cn/match/20第20题被置顶到了第1页,题目难度 写的是中等 算法很简单,就一个标准的md5算法,主要是盐值不确定, 而盐值就在wasm里面,可以说难点就在于wasm分析 sign参数分…...
【双指针优化DP】The 2022 Hangzhou Normal U Summer Trials H
Problem - H - Codeforces 题意: 思路: 首先很明显是DP 因为只有1e6个站点,因此可以以站点作为阶段 注意到K很小,因此可以尝试把这个当作第二维 设dp[i][j]为到达第i个站点,已经花了j元钱的最小步数 然后就想了一…...
[论文笔记] LLM数据集——金融数据集
一、chatglm_金融 ModelScope 魔搭社区 请将modelscope sdk升级到v1.7.2rc0,执行: pip3 install "modelscope1.7.2rc0" -f https://modelscope.oss-cn-beijing.aliyuncs.com/releases/repo.html # 方式1 git clone http://www.modelscope…...
在亚马逊平台,如何有效举报违规行为?
众所周知,在每个行业都有一些违规现象,甚至这些违规现象还会给自己带来利益方面的损失,一旦触犯到自己的利益的话,那自己是需要想办法解决的,想办法规避。 就拿开亚马逊店铺来说,比较容易遇到的就是产品侵…...
深度学习入门教学——神经网络
深度学习就是训练神经网络。 1、神经网络 举个最简单的例子,以下是一个使用线性回归来预测房屋价格的函数。这样一个用于预测房屋价格的函数被称作是一单个神经元。大一点的神经网络,就是将这些单个神经元叠加起来。例如:神经网络根据多个相…...
阿里Java开发手册~OOP 规约
1. 【强制】避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成 本,直接用 类名 来访问即可。 2. 【强制】所有的覆写方法,必须加 Override 注解。 说明: getObject() 与 get 0 bject() 的问题。…...
【Mysql数据库面试01】内连接 左连接 右连接 全连接
【Mysql数据库】内连接 左连接 右连接 全连接 0.准备1.内连接1.1 SQL(不带where)1.2 SQL(带where)1.3总结 2.左连接2.1SQL(不带where)2.2SQL(带where)2.3总结 3.右连接3.1 SQL(不带where&#x…...
事务隔离:为什么你改了我还看不见
前提概要 你肯定不陌生,和数据库打交道的时候,我们总是会用到事务。最经典的例子就 是转账,你要给朋友小王转 100 块钱,而此时你的银行卡只有 100 块钱。 转账过程具体到程序里会有一系列的操作,比如查询余额、做加减法…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...
ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...
BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...
Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...
VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
