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

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

动态内存管理

    • 1.1 为什么存在动态内存分配
    • 1.2 动态内存函数介绍
    • 2.1 malloc函数的使用
    • 2.2 free函数的使用
    • 2.3 calloc函数的使用
    • 2.4 realloc函数的使用
    • 3.1 常见的动态内存错误
    • 3.2 常见笔试题

1.1 为什么存在动态内存分配

我们已经掌握的内存开辟方式有:
int val = 20;//在栈空间上开辟四个字节
char arr[10] = { 0 };//在栈空间上开辟10个字节的连续空间
但是上述的开辟空间的方式有两个特点:
1. 空间开辟大小是固定的。
2. 数组在声明的时候,必须指定数组的长度,它所需要的内存在编译时分配。
但是对于空间的需求,不仅仅是上述的情况。有时候我们需要的空间大小在程序运行的时候才能知道,
那数组的编译时开辟空间的方式就不能满足了。
这时,就需要动态开辟内存了...

1.2 动态内存函数介绍

开辟内存

void* malloc (size_t size);

malloc函数是在堆中连续开辟size个字节的空间,返回值为空间的起始地址,开辟失败返回NULL指针

释放内存

void free (void* ptr);

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

2.1 malloc函数的使用

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>/*void* malloc( size_t size );
*/int main()
{int arr[10] = { 0 };// 动态内存开辟int* p = (int*)malloc(40); // 开辟40个字节if (p == NULL){printf("%s\n", strerror(errno));return 1; // 给main函数返回1表示存在问题}// 使用int i = 0;for (i = 0; i < 10; i++){*(p + i) = i;}for (i = 0; i < 10; i++){printf("%d ", *(p + i));}free(p);  // 释放内存空间,不然会内存泄漏,可以通过调试窗口 p,10 来观看数据p = NULL; // 防止野指针,因为它指向的空间已经释放了,已经还给操作系统了,p如果不置空的话,这时候还记得地址return 0;
}

还未free时的内存状态
在这里插入图片描述

free后的内存状况
在这里插入图片描述

p=NULL 是为了防止野指针,因为它指向的空间已经释放了,已经还给操作系统了,p如果不置空的话,这时候还记得地址,如果访问的话就非法访问内存了

2.2 free函数的使用

#include <stdio.h>
#include <stdlib.h>
int main()
{int a = 10;int* p = &a; // 不是动态开辟的free(p);p = NULL;int* p2 = NULL; // 什么事都不做free(p2);return 0;
}

free函数是只能释放动态内存的,不是动态开辟的会报错

在这里插入图片描述

2.3 calloc函数的使用

void* calloc (size_t num, size_t size);

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

#include  <stdio.h>
#include  <stdlib.h>
#include  <errno.h>
#include  <string.h>
int main()
{int* p = (int*)calloc(10, sizeof(int));if (p == NULL){printf("%s\n",strerror(errno));return 1;}int i = 0;for (i = 0; i < 10; i++) {printf("%d ",*(p+i));}// 释放堆中的内存free(p);p = NULL;return 0;
}

在这里插入图片描述

2.4 realloc函数的使用

void* realloc (void* ptr, size_t size);
#include  <stdio.h>
#include  <stdlib.h>
#include  <errno.h>
#include  <string.h>
int main()
{int* p = (int*)malloc(40);if (p == NULL){printf("%s\n", strerror(errno));return 1;}int i = 0;for (i = 0; i < 10; i++){*(p + i) = i;}// 扩容// 要用新的指针来接收并且判断,否则,如果扩容失败会变成野指针,本来指向40个字节,扩容失败突然指向NULLint* ptr = (int*)realloc(p, 80); if (ptr != NULL){p = ptr;}for (i = 0; i < 10; i++){printf("%d ", *(p + i));}free(p);p = NULL;return 0;
}

在这里插入图片描述

需要注意的事,realloc在开辟内存空间时,存在2种情况

在这里插入图片描述

malloc和realloc函数的关联


#include <stdio.h>
#include <stdlib.h>int main()
{int* ptr = (int*)realloc(NULL, 40); // 相当于 malloc(40)return 0;
}

3.1 常见的动态内存错误

1.对NULL指针的解引用操作

#include <stdio.h>
#include <stdlib.h>int main()
{int* p = (int*)malloc(40);if (p = NULL) // err{return 1;}*p = 20;free(p);p = NULL;return 0;
}

这里如果动态开辟内存失败,p为NULL,对NULL指针进行访问就会有问题

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

#include <stdio.h>
#include <stdlib.h>
int main()
{int* p = (int*)malloc(40);if (p = NULL){printf("%s\n", strerror(errno));return 1;}int i = 0;for (i = 0; i <= 10; i++) // 越界了{p[i] = i;}free(p);p = NULL;return 0;
}

3. 对非动态开辟内存使用free函数

#include <stdio.h>
#include <stdlib.h>int main()
{int a = 10;int* p = &a;free(p);p = NULL;return 0;
}

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

#include <stdio.h>
#include <stdlib.h>int main()
{int* p = (int*)malloc(40);if (p == NULL){return 1;}int i = 0;for (i = 0; i < 10; i++){// 这里p的位置被改变了,free(p)时,只释放掉了部分内存*p = i;p++;}free(p);p = NULL; return 0;
}

5. 对同一块空间的多次释放

#include <stdio.h>
#include <stdlib.h>int main()
{int* p = (int*)malloc(40);free(p);p = NULL; free(p);return 0;
}

6.动态开辟内存忘记释放(内存泄漏)

#include <stdio.h>
#include <stdlib.h>void test()
{int* p = (int*)malloc(100);int flag = 0;scanf("%d",&flag);if (flag == 5){return;}free(p);p = NULL;
}int main()
{test();return 0;
}

当flag为5时,就不会释放内存

3.2 常见笔试题

#include <stdio.h>
#include <stdlib.h>
#include <string.h>void GetMemory(char* p) // 堆中的p
{p = (char*)malloc(100);
}
void Test(void)
{char* str = NULL; // 栈中的pGetMemory(str); // 传递的是null,不是str的地址strcpy(str, "hello world"); // 将str给到空指针printf(str);
}int main()
{Test();return 0;
}

str为NULL,传递给GetMemory函数,GetMemory函数里的p是堆中的所开辟的p,然后给它开辟空间,然后返回到Test函数,这时的str依旧为NULL,然后调用strcpy函数,是把"hello world"给到NULL指针,会出现错误。

#include <stdio.h>char* GetMemory(void)
{char p[] = "hello world"; // 这里是局部变量,放置在栈中, 函数执行完就被销毁了,还给操作系统了//char* p = "hello world"; return p;
}
void Test(void)
{char* str = NULL;str = GetMemory(); // 野指针,非法访问内存了printf(str);
}int main()
{Test();return 0;
}

这里GetMemory后,返回的是局部变量的地址,放在栈中,但是这个函数执行完后这个变量就被销毁了,所以再通过指针访问这块内存空间就是非法访问内存了。

#include <string.h>
#include <stdio.h>
#include <stdlib.h>void GetMemory(char** p, int num)
{*p = (char*)malloc(num);
}
void Test(void)
{char* str = NULL;GetMemory(&str, 100);strcpy(str, "hello");printf(str);// 下列为修改后的代码//free(str);//str = NULL;
}int main()
{Test();return 0;
}

这个很容易,动态开辟内存后未能后free

在这里插入图片描述

相关文章:

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

动态内存管理 1.1 为什么存在动态内存分配1.2 动态内存函数介绍2.1 malloc函数的使用2.2 free函数的使用2.3 calloc函数的使用2.4 realloc函数的使用3.1 常见的动态内存错误3.2 常见笔试题 1.1 为什么存在动态内存分配 我们已经掌握的内存开辟方式有&#xff1a; int val 20;…...

Python实现基于TD3(Twin Delayed Deep Deterministic Policy Gradient)算法来实时更新路径规划算法

下面是一个使用Python实现基于TD3&#xff08;Twin Delayed Deep Deterministic Policy Gradient&#xff09;算法来实时更新路径规划算法的三个参数&#xff08;sigma0&#xff0c;rho0 和 theta&#xff09;的示例代码。该算法将依据障碍物环境进行优化。 实现思路 环境定义…...

pytorch实现半监督学习

半监督学习&#xff08;Semi-Supervised Learning&#xff0c;SSL&#xff09;结合了有监督学习和无监督学习的特点&#xff0c;通常用于部分数据有标签、部分数据无标签的场景。其主要步骤如下&#xff1a; 1. 数据准备 有标签数据&#xff08;Labeled Data&#xff09;&…...

我的毕设之路:(2)系统类型的论文写法

一般先进行毕设的设计与实现&#xff0c;再在现成毕设基础上进行描述形成文档&#xff0c;那么论文也就成形了。 1 需求分析&#xff1a;毕业设计根据开题报告和要求进行需求分析和功能确定&#xff0c;区分贴合主题的主要功能和拓展功能能&#xff0c;删除偏离无关紧要的功能…...

LosslessScaling-学习版[steam价值30元的游戏无损放大/补帧工具]

LosslessScaling 链接&#xff1a;https://pan.xunlei.com/s/VOHc-yZBgwBOoqtdZAv114ZTA1?pwdxiih# 解压后运行"A-绿化-解压后运行我.cmd"...

concurrent.futures.Future对象详解:利用线程池与进程池实现异步操作

concurrent.futures.Future对象详解&#xff1a;利用线程池与进程池实现异步操作 一、前言二、使用线程池三、使用进程池四、注意事项五、结语 一、前言 在现代编程中&#xff0c;异步操作已成为提升程序性能和响应速度的关键手段。Python的concurrent.futures模块为此提供了强…...

StarRocks 安装部署

StarRocks 安装部署 StarRocks端口&#xff1a; 官方《配置检查》有服务端口详细描述&#xff1a; https://docs.starrocks.io/zh/docs/deployment/environment_configurations/ StarRocks架构&#xff1a;https://docs.starrocks.io/zh/docs/introduction/Architecture/ Sta…...

Python Matplotlib库:从入门到精通

Python Matplotlib库&#xff1a;从入门到精通 在数据分析和科学计算领域&#xff0c;可视化是一项至关重要的技能。Matplotlib作为Python中最流行的绘图库之一&#xff0c;为我们提供了强大的绘图功能。本文将带你从Matplotlib的基础开始&#xff0c;逐步掌握其高级用法&…...

线程概念、操作

一、背景知识 1、地址空间进一步理解 在父子进程对同一变量进行修改时发生写时拷贝&#xff0c;这时候拷贝的基本单位是4KB&#xff0c;会将该变量所在的页框全拷贝一份&#xff0c;这是因为修改该变量很有可能会修改其周围的变量&#xff08;局部性原理&#xff09;&#xf…...

【PySide6拓展】QSoundEffect

文章目录 【PySide6拓展】QSoundEffect 音效播放类**基本概念****什么是 QSoundEffect&#xff1f;****QSoundEffect 的特点****安装 PySide6** **如何使用 QSoundEffect&#xff1f;****1. 播放音效****示例代码&#xff1a;播放音效** **代码解析****QSoundEffect 的高级用法…...

33【脚本解析语言】

脚本语言也叫解析语言 脚本一词&#xff0c;相信很多人都听过&#xff0c;那么什么是脚本语言&#xff0c;我们在开发时有一个调试功能&#xff0c;但是发布版是需要编译执行的&#xff0c;体积比较大&#xff0c;同时这使得我们每次更新都需要重新编译&#xff0c;客户再…...

【Unity】 HTFramework框架(五十九)快速开发编辑器工具(Assembly Viewer + ILSpy)

更新日期&#xff1a;2025年1月23日。 Github源码&#xff1a;[点我获取源码] Gitee源码&#xff1a;[点我获取源码] 索引 开发编辑器工具MouseRayTarget焦点视角Collider线框Assembly Viewer搜索程序集ILSpy反编译程序集搜索GizmosElement类找到Gizmos菜单找到Gizmos窗口分析A…...

如何解决TikTok网络不稳定的问题

TikTok是目前全球最受欢迎的短视频平台之一&#xff0c;凭借其丰富多彩的内容和社交功能吸引了数以亿计的用户。然而&#xff0c;尽管TikTok在世界范围内的使用情况不断增长&#xff0c;但不少用户在使用过程中仍然会遇到网络不稳定的问题。无论是在观看视频时遇到缓冲&#xf…...

告别页面刷新!如何使用AJAX和FormData优化Web表单提交

系列文章目录 01-从零开始学 HTML&#xff1a;构建网页的基本框架与技巧 02-HTML常见文本标签解析&#xff1a;从基础到进阶的全面指南 03-HTML从入门到精通&#xff1a;链接与图像标签全解析 04-HTML 列表标签全解析&#xff1a;无序与有序列表的深度应用 05-HTML表格标签全面…...

WireShark4.4.2浏览器网络调试指南:数据统计(八)

概述 Wireshark 是一款功能强大的开源网络协议分析软件&#xff0c;被广泛应用于网络调试和数据分析。随着互联网的发展&#xff0c;以及网络安全问题日益严峻&#xff0c;了解如何使用 Wireshark进行浏览器网络调试显得尤为重要。最新的 Wireshark4.4.2 提供了更加强大的功能…...

Hypium+python鸿蒙原生自动化安装配置

Hypiumpython自动化搭建 文章目录 Python安装pip源配置HDC安装Hypium安装DevEco Testing Hypium插件安装及使用方法​​​​​插件安装工程创建区域 Python安装 推荐从官网获取3.10版本&#xff0c;其他版本可能出现兼容性问题 Python下载地址 下载64/32bitwindows安装文件&am…...

2025创业思路和方向有哪些?

创业思路和方向是决定创业成功与否的关键因素。以下是一些基于找到的参考内容的创业思路和方向&#xff0c;旨在激发创业灵感&#xff1a; 一、技术创新与融合&#xff1a; 1、智能手机与云电视结合&#xff1a;开发集成智能手机功能的云电视&#xff0c;提供通讯、娱乐一体化体…...

实验五---控制系统的稳定性分析---自动控制原理实验课

一 实验目的 1、理解控制系统稳定性的概念 2、掌握多种判定系统稳定性的原理及方法 3、掌握使用Matlab软件进行控制系统的稳定性分析 二 实验仪器 计算机&#xff0c;MATLAB仿真软件 三 实验内容及步骤 1.计算系统闭环特征根&#xff0c;判别系统稳定性&#xff1b; 2.绘制系统…...

AttributeError: can‘t set attribute ‘lines‘

报错&#xff1a; ax p3.Axes3D(fig) ax.lines [] AttributeError: cant set attribute lines 总结下来&#xff0c;解决方案应包括&#xff1a; 1. 使用ax.clear()方法清除所有内容。 2. 逐个移除lines中的元素。 3. 检查matplotlib版本&#xff0c;确保没有已知的bug。…...

Day07:缓存-数据淘汰策略

Redis的数据淘汰策略有哪些 ? &#xff08;key过期导致的&#xff09; 在redis中提供了两种数据过期删除策略 第一种是惰性删除&#xff0c;在设置该key过期时间后&#xff0c;我们不去管它&#xff0c;当需要该key时&#xff0c;我们再检查其是否过期&#xff0c;如果过期&…...

SkyWalking 10.2.0 SWCK 配置过程

SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外&#xff0c;K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案&#xff0c;全安装在K8S群集中。 具体可参…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】

微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来&#xff0c;Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

微服务商城-商品微服务

数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

【HTTP三个基础问题】

面试官您好&#xff01;HTTP是超文本传输协议&#xff0c;是互联网上客户端和服务器之间传输超文本数据&#xff08;比如文字、图片、音频、视频等&#xff09;的核心协议&#xff0c;当前互联网应用最广泛的版本是HTTP1.1&#xff0c;它基于经典的C/S模型&#xff0c;也就是客…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...

无人机侦测与反制技术的进展与应用

国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机&#xff08;无人驾驶飞行器&#xff0c;UAV&#xff09;技术的快速发展&#xff0c;其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统&#xff0c;无人机的“黑飞”&…...

Python Einops库:深度学习中的张量操作革命

Einops&#xff08;爱因斯坦操作库&#xff09;就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库&#xff0c;用类似自然语言的表达式替代了晦涩的API调用&#xff0c;彻底改变了深度学习工程…...

PH热榜 | 2025-06-08

1. Thiings 标语&#xff1a;一套超过1900个免费AI生成的3D图标集合 介绍&#xff1a;Thiings是一个不断扩展的免费AI生成3D图标库&#xff0c;目前已有超过1900个图标。你可以按照主题浏览&#xff0c;生成自己的图标&#xff0c;或者下载整个图标集。所有图标都可以在个人或…...

向量几何的二元性:叉乘模长与内积投影的深层联系

在数学与物理的空间世界中&#xff0c;向量运算构成了理解几何结构的基石。叉乘&#xff08;外积&#xff09;与点积&#xff08;内积&#xff09;作为向量代数的两大支柱&#xff0c;表面上呈现出截然不同的几何意义与代数形式&#xff0c;却在深层次上揭示了向量间相互作用的…...