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

动态内存管理<C语言>

导言

        在C语言学习阶段,指针结构体动态内存管理,是后期学习数据结构的最重要的三大知识模块,也是C语言比较难的知识模块,但是“天下无难事”,只要认真踏实的学习,也能解决,所以下文将介绍动态内存管理涉及到的一些函数以及概念。


目录

导言

为什么存在动态内存管理

malloc和free

malloc

 free

calloc和realloc

calloc

 realloc

常见的关于动态内存管理错误

1.对可能是NULL指针的引用

 2.对不是动态开辟的内存进行释放

3.对动态开辟的内存进行越界访问

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

5.忘记内存释放(忘记free),造成内存泄漏

例题


为什么存在动态内存管理

int a;
char arr[10];

这是我们常用的用于向内存申请空间的办法,但是:

●空间开辟的空间是固定的

●数组在申明时,数组大小一旦确定,申请的内存空间不可变

在实际编写程序时,可能我们对于内存空间的需求不是固定,那么使用动态内存管理自己申请空间、自己释放空间就是一个很好的选择。


malloc和free

malloc

函数参数及其返回值

void* malloc(size_t size);
//申请size个字节的空间
//返回值,成功申请:返回开辟空间的首地址、失败:返回NULL

注意点

●返回值是void*,那么我们在实际使用时,应把它强制转化为我们需要的类型。

●与局部变量不同,开辟空间在堆区(如数组在栈区)

●malloc不会将内存空间初始化为0,这是与最大calloc区别!

●动态内存可调整(通过realloc)

使用举例:

 free

函数参数及其返回值

void free(void* ptr);
//释放动态内存申请的ptr指向的空间

注意点

●只能用来手动释放动态申请的空间,如果不是结果是未定义的

●释放空间后,只是将权限交还于操作系统,指针还指向着地址(悬空指针),应该手动将其置为NULL

●如果释放指针是NULL,那么什么也不做。

 使用举例:

#include<stdlib.h>
int main() {int* ptr = NULL;int count = 0;scanf("%d", &count);ptr = (int*)malloc(count * sizeof(int));free(ptr);ptr = NULL;return 0;
}

calloc和realloc

calloc

函数参数及其返回值

void* calloc(size_t num,size_t size);
//申请num个size个字节的空间,并初始化为0
//返回值,成功申请:返回开辟空间的首地址、失败:返回NULL

注意点

●开辟空间并全部初始化为0

●两个参数(num个size字节)

●其他与malloc类似

使用举例:

 realloc

 函数参数及其返回值

void* realloc(void* ptr,size_t size);
//ptr是要调整的内存地址
//size是调整之后的大小
//返回值,成功申请:返回调整空间的首地址、失败:返回NULL

使用举例:

#include<stdlib.h>
#include<stdio.h>
int main() {int count;scanf("%d", &count);int* ptr = (int*)calloc(count, sizeof(int));//申请count个int大小的空间if (ptr) {//判断是不是NULL:是否申请成功for (int i = 0; i < count; i++)ptr[i] = i;//赋值:从0开始到count-1步为1的序列for (int i = 0; i < count; i++)printf("%d ", ptr[i]);}printf("\n");printf("调整前的地址:%p\n", ptr);//观察动态(realloc)调整前的地址int* p = (int*)realloc(ptr, (count + 5) * sizeof(int));//申明一个新指针来接收,防止调整失败返回NULL,数据丢失,调整为多5个int大小的地址if (p)//判断是否是NULL:是否调整成功ptr = p;printf("调整后的地址:%p", ptr);//观察动态(realloc)调整后的地址free(ptr);ptr = NULL;return 0;
}

运行结果:

先开辟10个int字节大小空间的运行结果:

 先开辟20个int字节大小空间的运行结果:

注意点

●参数size为0时,返回值是NULL,并将ptr的内存释放,这是未定义的行为,在不同的编译器上不能保证

●如果ptr参数为NULL,会动态开辟一个新的内存空间,此时realloc函数的作用等同于malloc

●这个函数调整空间时会把数据移到的内存空间内(实际上,有一种情况不会,但是为了代码的健壮性和可移植性,我们最好这样定义)

两种情况:

①原有地址后面足够的空间容纳调整后的空间

②原有地址后面没有足够的空间容纳调整后的空间

其实在前面的使用举例中我们已经观察到:

先开辟10个int字节大小空间的运行结果(第一种情况)

        直接在原地址后面开辟新空间

先开辟20个int字节大小空间的运行结果(第二种情况)

        找到一块能容纳调整后的空间的地址,将数据移动到其中

关于参数size为0时的举例:

因为我们没有办法直接观察一块动态开辟的内存是否被释放,且这种size为0行为是未定义的,所以我们只能观察它的返回值

 

 关于参数ptr是NULL时的情况

此时realloc等同malloc

注意:动态内存管理的4个函数都包含在<stdlib.h>中


常见的关于动态内存管理错误

1.对可能是NULL指针的引用

 

 2.对不是动态开辟的内存进行释放
// 2.对不是动态开辟的内存进行释放
#include<stdio.h>
#include<stdlib.h>
int main() {int a = 0;int* p = &a;free(p);p = NULL;return 0;
}

3.对动态开辟的内存进行越界访问
//3.对动态开辟的内存进行越界访问
#include<stdlib.h>
int main() {int* p = (int*)malloc(sizeof(int));p++;*p = 1;free(p);p = NULL;return 0;
}

4.使用free释放动态开辟内存的一部分
//4.使用free释放动态开辟内存的一部分
#include<stdlib.h>
int main() {int* p = (int*)malloc(4*sizeof(int));//动态开辟4个int大小的空间p++;//指向第二个元素free(p);p = NULL;return 0;
}

5.忘记内存释放(忘记free),造成内存泄漏
//5.忘记内存释放(忘记free),造成内存泄漏
#include<stdlib.h>
int main() {int* p = (int*)malloc(sizeof(int));return 0;
}

例题

1.

void GetMemory(char* p)
{p = (char*)malloc(100);
}
void Test(void)
{char* str = NULL;GetMemory(str);strcpy(str, "hello world");printf(str);
}
int main() {Test();return 0;
}运行会咋样

p虽然在GetMemory函数中开辟了内存,但是在出函数时,该地址被销毁,所以str还是NULL指针,对NULL指针进行赋值是一个未定义行为。(传值调用而没有使用传址调用)

改正(二级指针):

void GetMemory(char** p)//使用二级指针接收
{*p = (char*)malloc(100);
}
void Test(void)
{char* str = NULL;GetMemory(&str);//传入指针的地址strcpy(str, "hello world");printf(str);
}
int main() {Test();return 0;
}

改正(将开辟的空间返回):

2.

char* GetMemory(void)
{char p[] = "hello world";return p;
}
void Test(void)
{char* str = NULL;str = GetMemory();printf(str);
}
int main() {Test();return 0;
}//运行结果?

GetMemory函数返回了一个地址,但是这个地址出了函数,权限已经收回给了操作系统,str接收的是一个野指针,并将它打印出来,这种行为是未定义的,可能造成错误。(说到底是栈空间返回会被销毁的问题)

我们知道只要是函数内的变量都是栈空间申请的空间,在出函数时,都会被回收,但是动态内存管理申请的空间,必须要手动释放,所以在函数中我们使用动态内存申请的地址是不会被收回的(堆区申请),所以我们尝试改正时,在函数内部使用动态内存申请,并返回。

改正:

char* GetMemory(void)
{char* p = (char*)malloc(20);strcpy(p, "hello world!");return p;
}
void Test(void)
{char* str = NULL;str = GetMemory();printf(str);
}
int main() {Test();return 0;
}

3.

//3
void GetMemory(char** p, int num)
{*p = (char*)malloc(num);
}
void Test(void)
{char* str = NULL;GetMemory(&str, 100);strcpy(str, "hello");printf(str);
}
int main() {Test();return 0;
}//运行结果,以及问题

没释放空间,内存泄漏

改正:

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(ptr);ptr=NULL;
}
int main() {Test();return 0;
}

使用了已经被释放的内存

相关文章:

动态内存管理<C语言>

导言 在C语言学习阶段&#xff0c;指针、结构体和动态内存管理&#xff0c;是后期学习数据结构的最重要的三大知识模块&#xff0c;也是C语言比较难的知识模块&#xff0c;但是“天下无难事”&#xff0c;只要认真踏实的学习&#xff0c;也能解决&#xff0c;所以下文将介绍动态…...

第一百零二节 Java面向对象设计 - Java静态内部类

Java面向对象设计 - Java静态内部类 静态成员类不是内部类 在另一个类的主体中定义的成员类可以声明为静态。 例子 以下代码声明了顶级类A和静态成员类B&#xff1a; class A {// Static member classpublic static class B {// Body for class B goes here} }注意 静态成…...

给自己Linux搞个『回收站』,防止文件误删除

linux没有像windows里一样的回收站&#xff0c;工作时候删除文件容易不小心删错&#xff0c;造成麻烦的后果。所以给自己整了个回收站&#xff1a; 文件删除&#xff0c;新建~/opts/move_to_trash.sh&#xff0c;然后在里面新增&#xff0c;将${your_name}改成你的用户名。同时…...

Springboot接收参数的21种方式

前言 最近一直在忙着开发项目(ps:其实有些摆烂),好久没有更新博客了,打开csdn一看好多网友留言私信,继上篇博客(我是如何实现HttpGet请求传body参数的!),网友议论纷纷,各抒起见。今天正好抽出时间总结一下Springboot接受参数的21种方式(Post、Get、Delete),一并…...

打造出色开发者体验的十大原则

大约十年前我是一名CIO&#xff0c;当时我在评估一种技术解决方案&#xff0c;向潜在供应商的代表讲明了我们的主要需求。他展示了该公司的至少三款产品。每种工具都有各自的用户体验、开发方法和学习要求&#xff0c;但是解决我们的业务需求同时需要这三种工具。作为CIO&#…...

Vue3_对接腾讯云COS_大文件分片上传和下载

目录 一、腾讯云后台配置 二、安装SDK 1.script 引入方式 2.webpack 引入方式 三、文件上传 1.new COS 实例 2.上传文件 四、文件下载 腾讯云官方文档&#xff1a; 腾讯云官方文档https://cloud.tencent.com/document/product/436/11459 一、腾讯云后台配置 1.登录 对…...

python免杀--base64加密(GG)

单层加密都GG~ 目录 cs生成个python的payload 将shellcode进行base64编码 执行上线代码 cs生成个python的payload msfvenom -p windows/meterpreter/reverse_tcp --encrypt base64 lhostIP lport6688 -f c cs生成c的也行. 将shellcode进行base64编码 import base64code …...

Python版与Java版城市天气信息爬取对比分析

在对比Python版和Java版城市天气信息爬取时&#xff0c;我们需要考虑多个方面&#xff0c;包括语言特性、库支持、代码简洁性、执行效率以及维护成本等。以下是对这两个版本进行的一些对比分析&#xff1a; 1. 语言特性 Python&#xff1a; 易于学习&#xff1a;Python的语法清…...

CSS真题合集(二)

CSS真题合集&#xff08;二&#xff09; 11. css3新增特性12. css3动画12.1 关键帧动画 (keyframes)12.2 animation12.3 transition12.4 transform 13. grid网格布局13.1 使用display: grid或display: inline-grid的HTML元素。13.2 定义网格13.3 13.4 自动填充和自动放置13.4 对…...

长期出汗困扰你?可能是肾合出了问题

想象一下&#xff0c;我们的身体是一座繁茂的秘密花园&#xff0c;每一寸肌肤、每一个细胞都是花园里的一朵花、一片叶。汗水&#xff0c;则是这花园中无声的语言&#xff0c;它讲述着我们的健康与否&#xff0c;也揭示着身体内部的微妙变化。 在炎炎夏日&#xff0c;身体如盛开…...

Jmeter函数二次开发说明

jmeter 二次开发使用 jmeter二次开发实现方法 使用maven依賴进行开发 导入jmeter的maven依赖&#xff0c;需要和你使用的jmeter版本一致。 <!-- https://mvnrepository.com/artifact/org.apache.jmeter/ApacheJMeter_core --> <dependency><groupId>org.ap…...

重新学习STM32(1)GPIO

概念简介 GPIO 是通用输入输出端口的简称&#xff0c;简单来说就是 STM32 可控制的引脚。STM32 芯片通过 GPIO 引脚与外部设备连接起来&#xff0c;从而实现与外部通讯、控制以及数据采集的功能。 GPIO被分成很多组&#xff0c;比如 GPIOA和GPIOB等。所有的 GPIO引脚都有基本的…...

React+TS前台项目实战(二)-- 路由配置 + 组件懒加载 + Error Boundary使用

文章目录 前言一、路由配置和懒加载lazy的使用二、TS版本Error Boundary组件封装三、在layout组件中使用Suspense组件和错误边界组件总结 前言 本文将详细介绍项目中的页面路由配置和异步组件懒加载处理&#xff0c;以提高用户体验&#xff0c;实现过渡效果。 一、路由配置和懒…...

成为电商低价神秘顾客访问员的必备条件(深圳神秘顾客公司)

电商低价神秘顾客需要具备以下条件&#xff0c;以确保能够执行有效的调查任务并为企业提供有价值的反馈&#xff1a; 1、细致的观察能力&#xff1a;神秘顾客访问员需要具备细致的观察能力&#xff0c;能够全面、细致地观察电商平台的购物流程、商品详情、服务细节等。这包括注…...

现货黄金交易多少克一手?国内外情况大不同

如果大家想参与国际市场上的现货黄金交易&#xff0c;就应该从它交易细则的入手&#xff0c;先彻底认识这个品种&#xff0c;因为它是来自欧美市场的投资方式&#xff0c;所以无论是从合约的计的单位&#xff0c;计价的货币&#xff0c;交易的具体时间&#xff0c;以及买卖过程…...

LNMP与动静态网站介绍

Nginx发展 Nginx nginx http server Nginx是俄罗斯人 Igor Sysoev(伊戈尔.塞索耶夫)开发的一款高性能的HTTP和反向代理服务器。 Nginx以高效的epoll.kqueue,eventport作为网络IO模型&#xff0c;在高并发场景下&#xff0c;Nginx能够轻松支持5w并发连接数的响应&#xff0c;并…...

教育小程序开发:技术实现与实践案例

随着信息技术的不断进步&#xff0c;教育小程序在教育领域的应用越来越广泛。教育小程序开发不仅可以提高教学效率&#xff0c;还能够提供个性化的学习体验。本文将以技术代码为例&#xff0c;详细介绍教育小程序开发的关键技术和实践案例&#xff0c;帮助开发者更好地理解和实…...

LeetCode 746.使用最小花费爬楼梯

题目&#xff1a; 给你一个整数数组 cost &#xff0c;其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用&#xff0c;即可选择向上爬一个或者两个台阶。 你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。 请你计算并返回达到楼梯顶部的最低花费…...

软件设计模式概述

一 软件模式概述 软件设计模式是在软件开发过程中经过验证的、可重复使用的最佳实践。 它们提供了解决常见设计问题的模板和指导方针&#xff0c;有助于开发人员编写高质量、可维护和可扩展的代码。 软件设计模式通常基于面向对象的编程范式&#xff0c;并利用封装、…...

短剧片源火爆,千金难求好剧源

前言 在当今快节奏的生活中&#xff0c;短剧以其精悍的篇幅、吸睛的剧情和便捷的观看方式&#xff0c;异军突起&#xff0c;吸引了大量观众的关注和喜爱。这些短剧不仅让人们在忙碌的间隙轻松娱乐&#xff0c;更以其高潮迭起的情节设计&#xff0c;让观众在短时间内便能体验到…...

MES系统定制 | 生产调度车间排班计划/MES排程排产

MES系统是一种集成化的生产信息化管理系统&#xff0c;通过实时收集和分析车间生产数据&#xff0c;帮助企业实现生产过程的自动化控制和监测。它可以跟踪生产计划、设备状态、物料流动等关键指标&#xff0c;并提供实时报表和决策支持。在这个系统中&#xff0c;车间班次排班是…...

【Anaconda】 anaconda常用命令总结

【Anaconda】 anaconda常用命令总结 一、创建虚拟环境二、激活/使用/进入某个虚拟环境三、退出当前环境四、复制某个虚拟环境五、删除某个环境六、查看当前所有环境七、查看当前虚拟环境下的所有安装包八、安装或卸载包(进入虚拟环境之后&#xff09;九、分享虚拟环境十、源服务…...

VIsio Professional 绘图

...

Flutter InAppWebView Unknown feature SUPPRESS_ERROR_PAGE

在使用InAppWebView的initialData加载html代码的时候,出现java.lang.RuntimeException: Unknown feature SUPPRESS_ERROR_PAGE的出错误 E/MethodChannel#flutter/platform_views(16853): Failed to handle method call E/MethodChannel#flutter/platform_views(16853):<...

linux系统PXE自动装机和无人值守

一、PXE 1.PXE&#xff1a;c/s模式&#xff0c;允许客户端通过网络从远程服务器&#xff08;服务端&#xff09;下载引导镜像&#xff0c;加载安装文件&#xff0c;实现自动化安装操作系统。&#xff08;c/s客户端和服务端都可以是多台&#xff09; 2.PXE优点&#xff1a;规模…...

大模型的高考数学成绩单:及格已经非常好了

让考生头皮发麻的高考数学&#xff0c;可难倒了顶尖 AI 大模型。 一年一度的高考即将落幕&#xff0c;衷心希望各位考生都超常发挥&#xff0c;考出满意的好成绩&#xff01;&#xff01; 和往年一样&#xff0c;除了让 AI 大模型写写高考作文&#xff0c;我们也选取了六家国…...

【漏洞复现】CraftCMS ConditionsController.php 代码执行漏洞(CVE-2023-41892)

0x01 产品简介 Crat CMS是一个开源的内容管理系统&#xff0c;它专注于用户友好的内容创建过程&#xff0c;逻辑清晰明了&#xff0c;是一个高度自由&#xff0c;高度自定义设计的平台&#xff0c;可以用来创建个人或企业网站也可以搭建企业级电子商务系统。 0x02 漏洞概述 …...

代码随想录算法训练营第三十八 |● 509. 斐波那契数 ● 70. 爬楼梯 ● 746. 使用最小花费爬楼梯

我在每一个算法开始之前都会去认真的看一下这个理论基础&#xff0c;或者说是算法的主要思想&#xff0c;可以直接看视频carl讲解的很清晰&#xff1b;其次还会大致看一下这一part中的题型及难度 动态规划理论基础讲解链接&#xff1a;https://programmercarl.com/%E5%8A%A8%E6…...

如何有效处理服务器后台密码暴露

服务器后台密码的暴露是信息安全领域中的严重事件&#xff0c;它可能引发未经授权的数据访问、恶意软件植入或系统功能滥用等一系列问题。本文将探讨几种处理服务器后台密码暴露的有效策略&#xff0c;包括紧急响应步骤、密码安全增强措施及长期预防机制&#xff0c;并提供实际…...

使用本地大模型调用代码,根本就是一场骗局!

通过大模型调用其他工具到底可不可行&#xff1f;ChatGPT 或许能轻松搞定一切&#xff0c;但同样的需求落在本地大模型上&#xff0c;恐怕就要打个问号了。 法国开发工程师 Emilien Lancelot 尝试了多款号称具备工具调用功能的 agent 框架&#xff0c;来看看本地大模型到底能不…...

做网站用哪种编程语言/seo搜索引擎入门教程

早些时戴尔发布了SAN Headquarters(SAN HQ) v2.2。这个版本的SAN HQ给用户带来了一些全新的和令人激动的特性。 如果您已经是SAN HQ的用户了&#xff0c;您应该能够意识到SAN HQ的诸多益处。通过发现性能的瓶颈&#xff0c;SAN HQ可以改善整个SAN系统的性能。通过发现那些未被有…...

2008 iis 配置 asp网站/网站建设需要多少钱

本人在开发机器软件的时候&#xff0c;以为一个工程生成一个文件&#xff0c;其他的文件不影响。所以在生成目录不同的时候&#xff0c;会造成只拷贝单个文件程序运行不正常的现象。 描述如下&#xff1a;有一个WPF工程A&#xff0c;引用了3个动态库B.C.D&#xff0c;编译时输出…...

wordpress 内页插件/搭建网站

原文出处&#xff1a; 微软互联网开发支持 Visual Studio 是一个强大的调试工具&#xff0c;里面很多隐藏功能少有人问津&#xff0c;但是在特定场景可以节省你很多时间&#xff0c;本文主要介绍一些Visual Studio调试相关的隐藏功能&#xff0c;欢迎大家补充。 运行到光标(R…...

安徽建设通网站/seo网站结构优化的方法

http://video.jessetalk.cn/转载于:https://www.cnblogs.com/lkd3063601/p/8547733.html...

网站模板在线演示怎么做/网站seo哪里做的好

前两天家里的网断断续续&#xff0c;发现有人在用arp欺骗&#xff0c;其实真正碰到有人在攻击的几率不大&#xff0c;大部分原因都是有人在用win下的诸如“P2P终结者”这样的软件导致的。再怎么bs那人也是没有用的&#xff0c;问题还是要解决&#xff0c;win下倒是好办&#xf…...

巴南城乡建设网站/泽成杭州seo网站推广排名

VMware服务随意关发表时间&#xff1a; 2008年04月23日 00时48分 评论/阅读(/)本文地址&#xff1a; http://qzone.qq.com/blog/280883610-1208882895VMware 虚拟机程序安装后同时会有4个服务打开&#xff0c;极大的消耗了系统资源&#xff0c;对我这样的铁公鸡来说实在…...