(超详解)---->> 动态内存管理

news/2023/12/9 16:22:16

目录

本章重点

        1:malloc,calloc,realloc,free 函数

        2:常见动态内存错误

        3:几道经典的笔试题


1:malloc,calloc,realloc,free函数

        首先我们平时所创建的变量数组都是在栈区上开辟的内存,空间开辟的大小固定的。

        而有些程序是要在运行的时候它所需要的空间才能知道。

        这4个函数在内存中使用的时候是在堆区开辟空间的。

        malloc:使用语法是malloc(size_byte);,size_byte指的是需要开辟多少字节空间的内存,malloc函数的返回值开辟空间的地址类型为void*,所以在使用的时候我们需要根据需求来强制类型转换

        malloc开辟空间的时候可能不会成功的开辟,如果失败的话则返回NULL,所以一般在使用完malloc开辟的空间之后我们会对地址来进行判断,这样可以及时提醒我们是否开辟空间成功。

malloc对于开辟的空间的内容不会初始化,且最后我们需要借助free函数释放我们所开辟的空间。对于malloc(0)这个行为是未定义的。

        free:使用语法是free(ptr),这里的ptr是一个指针,返回值为void,函数参数为void*的指针,它是用来释放动态内存开辟的空间,对于非动态内存开辟的空间如果用free来释放,那么程序可能会直接报错,如果对与NULL指针释放,及free(NULL),这时我们的free啥都不会做

        calloc:使用语法为calloc(num,size),num表示要开辟多少个数量size表示每个空间的大小,单位是字节,函数功能是开辟num个大小为size的空间开辟成功返回值为开辟空间的地址,开辟失败返回值为NULL与malloc最主要的区别就是它开辟完空间之后会将每个字节的空间大小全部初始化为0如下图:>

 所有当我们到底使用malloc还是calloc我们可以看我们是否需要初始化空间。

realloc:它是用来调整我们动态内存开辟空间大小的,有时我们开辟的空间过小,也有时我们开辟的空间过大,我们都可以用realloc来调整我们动态内存空间的大小,所有realloc函数的出现使我们

更加合理的来动态内存管理

        

realloc函数的原型
void* realloc (void* ptr, size_t size);ptr:代表我们所需要调整空间的地址
size:表示我们需要重新调整空间的大小,单位是字节

        当realloc需要扩容的时候,会出现两种情况:>

        情况1:当realloc所开辟的空间的大小在原空间后面有足够大的空间,那么realloc的返回值还是需要调整空间的地址

 

情况2:原空间后面没有多余的空间,则在这时我们的realloc函数会在堆区寻找另外一块足够大的空间去申请一块空间,这时realloc会自动将原空间的内容拷贝到新开辟的空间处,并且realloc函数会自动释放原来地址的空间,然后返回新的空间的起始地址

 

 

2:常见的动态内存错误

常见错误1:对NULL解引用操作

void test()
{int *p = (int *)malloc(INT_MAX/4);*p = 20;free(p);
}
int main()
{test();   return 0;
}

解释:因为INT_MAX,是整形取值的最大值,而用malloc去开辟空间的时候可能会失败,所以p可能是NULL,此时*p则代表对空指针进行解引用,此时属于非法访问内存了。

解决办法:对于刚开辟出来的空间我们就对其进行判断,并且如果申请空间失败就直接退出程序。

常见错误2:越界访问内存

void test()
{int i = 0;int *p = (int *)malloc(10*sizeof(int));if(NULL == p){exit(EXIT_FAILURE);}for(i=0; i<=10; i++){*(p+i) = i;//当i是10的时候越界访问}free(p);
}

解释:我们知道p是一个(int*)类型的指针,p+i则代表跳过i个整形而在此处的代码当中,当i等于10的时候,我们p跳过10个整形刚好跳过我们申请的空间,而此时在对p进行解引用操作,则算属于非法访问内存,程序会崩溃的。

图解:

解决办法:对于开辟出来空间的大小我们要牢记,防止非法访问其他内存的空间。

常见错误3:对非动态开辟的空间进行释放

void test()
{int a = 10;int *p = &a;free(p);//ok?}

 这里的a是在栈区开辟的空间,而free函数是对动态内存开辟的空间进行释放的。所以这个程序是error的

解决办法:牢记free函数的作用,是对动态开辟的内存空间进行释放的。

常见错误4:释放一部分动态内存空间

void test()
{int *p = (int *)malloc(100);p++;free(p);//p不再指向动态内存的起始位置}

解释:在这里p是开辟的空间的地址,且又是整形指针所以+1则代表跳过1个整形的地址,所以这里的p不在是指向内存的首地址了。所以只对申请空间的一部分进行了释放,还是会存在内存泄漏的,所以这也是一个错误。

解决办法:对于开辟出来的空间的地址我们不要进行移动。

常见错误5:对同一块内存空间进行多次释放

void test()
{int*p=(int*)malloc(100);free(p);free(p);}

 解释:在这里对p进行了多次释放,第一次释放是正确的是对自己申请的空间进行释放,而第二次释放的时候就是错误的了,因为第二次的释放是对空间的非法访问。所以也是error的,当然在说这些前提下我们都认为我们申请的空间是有效的。

解决办法:开辟一次,释放一次。

常见错误6:对动态内存开辟的空间未释放,形成内存泄漏

void test()
{int* p =(int*)malloc(100);if(p!=NULL){*p=20;}}int main()
{test();while(1);return 0;
}

解释:当我们调用test函数结束后,因为p是一个局部变量是在栈区上开辟的,所以出了test函数的作用域后,p就会销毁,而我们也为对开辟出来的空间进行释放,所以我们就会浪费这100个字节的空间,所以就会形成内存泄漏的问题。

解决办法:当我们开辟出来的空间没有进行使用得时候我们一定要记得释放这一块空间。

3:经典笔试题

题目1:

void GetMemory(char* p)
{p=(char*)malloc(100);
}void Test(void){char*  str =NULL;GetMemory(str);strcpy(str,"hello world");printf(str);
}

解释:首先这个程序是错误的,因为对NULL进行了非法访问,str一开始是NULL,GetMemory(str),想法是给str开辟一块空间,可是我们要记住,p是一个形式参数,会独自开辟内存空间,对形式参数的影响不会影响实参。且该函数还存在内存泄漏的问题

 题目2:

char* GetMemory(void)
{char p[] ="hello world";return p;
}
void Test(void)
{char* str =NULL;str =GetMemory();printf(str);
}

解释:在GetMemory函数当中,p是一个数组,p是指向"hello world",出函数就会销毁,而此时将p的值给str,尽管此时我们的str还是指向曾今的那块空间的地址,可是出了函数范围的时候,这块空间就会还给操作系统,所以此时的str是一个野指针打印出来的就是烫烫烫...属于返回栈空间地址的问题。

题目3:

void GetMemory(char** p, int num)
{*p = (char*)malloc(num);
}void test()
{char* str = NULL;GetMemory(&str, 100);strcpy(str, "hello world");printf(str);
}
int main()
{test();return 0;
}

解释:这个程序可以打印出来结果,就是当我们使用完开辟的空间后未进行内存的释放,会形成内存泄漏的问题。

题目4:

void Test()
{char* str = (char*)malloc(100);strcpy(str, "hello");free(str);if (str != NULL){strcpy(str, "world");printf(str);}}

解释:这段代码虽然可以在vs中打印出来,但是这段代码还是有问题的。

       因为我们已近对str这块空间先释放的,所以已近将这块空间还给操作系统了,而此时str还是指向那块空间的地址,所以world还是会被拷贝进去。但是这已近形成非法访问内存了。所以我们在日常敲代码的过程中如果已近将某一块空间给释放了,我们一定要将指针置为空,这样我们才不会形成非法访问内存的可能。

                                感谢大家的观看!


http://www.ppmy.cn/news/887239.html

相关文章

spring cloud 之 Hystrix

Hystrix概述 Hystrix是一个供分布式系统使用&#xff0c;提供延迟和容错功能&#xff0c;保证复杂的分布系统在面临不可避免的失败是时&#xff0c;仍具有弹性。 当服务器A调用服务器B时&#xff0c;如果服务器B宕机&#xff0c;则服务器A不去调用。当服务器B在时间范围内未响…

输入年月日判断是一年里的第几天

import java.util.Scanner;public class K612 {public static void main(String[] args) {Scanner anew Scanner(System.in);//判断是一年里的第几天int days0;System.out.println("输入年");int yeara.nextInt();System.out.println("输入月");int mounth…

常用UAPROFILE下载地址

If you’re interested in the capabilities of a particular device, I have assembled a list of all the UAProf URLs from the WURFL database: AirnessAir99 http://www.airnessmobile.com/uaprof/Airn… slide99 http://www.airnessmobile.com/uaprof/slid… AlcatelMand…

CENTREX业务简介

CENTREX业务简介 市内电话业务作业要点称为集中式数位小交换机 (CENTRalized EXchange,简称CENTREX,又称虚拟总机),系利用软体将用户专用交换机(俗称总机,PBX)之功能内建在局用市话交换机上,直接由局用交换机提供PBX服务功能.亦即由局用交换机扮演虚拟PBX之角色,CENTREX群之分机…

matlab 曲线数据输出,Mathlab 如何输出曲线各数据点值?

编了个程序,得到了预期的多条x-y曲线,但是想得到各时间点的具体值。研究了好几天,还是做不出。 哪位高手能演示下? 随便输出哪一条曲线都可以。 程序如下: function IV tspan=[0, 30]; x0 = [0 0 0 0 0 100 0 0 0 0 0 0 0 0 0 0 100]; [T, X] = ode45(@lun_fun, tspan,…

LabVIEW开发图像采集和图像处理程序

LabVIEW开发图像采集和图像处理程序 扫描电子显微镜&#xff08;SEM&#xff09;是一种功能强大的工具&#xff0c;广泛用于高分辨率的生物和半导体样品检测。然而&#xff0c;对于大面积或3D成像&#xff0c;SEM成像是一个耗时的过程。MBSEM旨在通过同时扫描多个像素来减少采…

PyTorch翻译官网教程7-OPTIMIZING MODEL PARAMETERS

官网链接 Optimizing Model Parameters — PyTorch Tutorials 2.0.1cu117 documentation 优化模型参数 现在我们有了一个模型和数据&#xff0c;是时候通过优化我们的数据参数来训练、验证和测试我们的模型了。训练模型是一个迭代过程;在每次迭代中&#xff0c;模型对输出进…

计算机主机检测不到耳机,win10电脑检测不到耳机怎么办_win10电脑检测不到耳机如何解决-系统城...

日常在使用win10电脑听歌曲时喜欢插入耳机&#xff0c;这样音质比直接外放好多了&#xff0c;最近很多win10用户出现了耳机拔下来再插上电脑然后耳机听不到声音&#xff0c;检测耳机是没问题的&#xff0c;那么就是设置出现问题&#xff0c;针对此故障&#xff0c;小编这里和大…

计算机主机检测不到耳机,win10电脑检测不到耳机的原因及处理方法

日常在使用 具体方法如下&#xff1a; 1、首先我们要确保耳机本身没有问题&#xff0c;然后再插入电脑&#xff0c;如果还是出现下图所示情况&#xff0c;就往下看。 2、 接着&#xff0c;我们下载安装软件“驱动精灵”&#xff0c;用这个软件卸载安装声卡驱动&#xff0c;确保…

Cell 子刊 | 深度睡眠脑电波调节胰岛素敏感性促进血糖调节

缺乏高质量的睡眠会增加一个人患糖尿病的风险。然而&#xff0c;为什么会这样仍然是一个不解之谜。 近期&#xff0c;加州大学伯克利分校的一组睡眠科学家的新发现为我们揭示了答案。研究人员在人体内发现了一种潜在的调控机制&#xff0c;解释了为什么夜间深度睡眠脑电波能够调…

MFC扩展库BCGControlBar Pro v33.5新版亮点 - 其他增强功能

BCGControlBar库拥有500多个经过全面设计、测试和充分记录的MFC扩展类。 我们的组件可以轻松地集成到您的应用程序中&#xff0c;并为您节省数百个开发和调试时间。 BCGControlBar专业版 v33.5已正式发布了&#xff0c;此版本包含了Ribbon&#xff08;功能区&#xff09;自定义…

约汗——基于Android的大学生找伙伴约运动app 开发总结

最近和小伙伴花了四天时间赶工&#xff0c;把我们的约汗app部分功能模块 实现了。虽然并不是尽善尽美&#xff0c;但加班加点熬夜做的东西&#xff0c; 确实是在竭尽全力。下面来简略地说一下和这次开发有关的事吧。 职责 我的小伙伴主要是负责UI设计&#xff0c;前端开发。…

正逆运动学+动力学仿真

​【前言】最近看到一些留言在寻找源码&#xff0c;现整理了全部分享出来&#xff0c;其中包括正逆运动学解算、雅克比矩阵应用&#xff08;主要用于关节力矩的计算&#xff09;&#xff0c;需要的小伙伴自取。 一、平面二连杆运动学建模 二、平面二连杆动力学建模 应用背景&a…

微信、QQ、支付宝运动步数自定义小工具

前言 冬天了&#xff0c;外面寒风刺骨&#xff0c;给不少朋友带来很多困扰 天冷、风大、下雪都不想出门&#xff0c;又想给蚂蚁森林浇水、捐步数怎么办~ 今天再次分享给你们一个可以在恶劣天气下偷偷懒的小工具&#xff0c;可以自由定义自己V、Q、ZFB等平台的运动量&#xf…

2017年春招“森林举行运动会”编程题

森林举行运动会&#xff0c;小伙伴们身上每个都印着一个字符标记&#xff0c;排成一列&#xff0c;委员会要挑出每列里相邻小伙伴身上没有重复字符标记的&#xff0c;最多能挑出几个&#xff1f; 比如&#xff1a;小伙伴们的字符标记串起来是“ccccccbc” 那相邻的小伙伴身上没…

机械臂运动学逆解

机械臂正逆解 由于贫穷的关系&#xff0c;只得在淘宝上购买“玩具”机械臂进行研究&#xff0c;这是下面这货&#xff1a; 2022年2月更&#xff1a;之前的这个求解方式对于姿态的约束是有一些问题的&#xff0c;此课程包含了修正后的3、4自由度机械臂的逆解推导与源码&#xff…

单麦克纳姆轮受力分析

关注同名微信公众号“混沌无形”&#xff0c;阅读更多有趣好文&#xff01; 原文链接&#xff1a;https://mp.weixin.qq.com/s/sjb3O91auADKN7iDsut0jA&#xff08;包含原文PDF百度云下载链接&#xff09; 图 2.1 麦克纳姆轮结构示意图. &#xff08;a&#xff09;轮结构分析, …

全向轮机器人运动模型及应用分析

[文末提供原文PDF免费下载(期刊论文版式)] 混沌无形 混沌系统是世界本质&#xff0c;无形之中存在规律。机器人智能化发展从线性过渡到混沌&#xff0c;本号将分享机器人全栈技术&#xff08;感知、规划、控制&#xff1b;软件、机械、硬件等&#xff09;。 43篇原创内容 公…

ROS小车三轴全向轮底座运动学分析

914无人机创新实验室上课了。 最近几天时间里&#xff0c;实验室的小伙伴研究了ROS小车的三轴全向轮底座的运动学原理&#xff0c;并稍有收获&#xff0c;现加以整理记录。 一、全向轮基础知识 全向轮由于能够向着与轴承垂直的方向运动&#xff0c;同时能依靠从动轮向着与轴承的…

三轴全向机器人运动学分析

前言&#xff1a;机器人日趋火热&#xff0c;各式各样的机器人随即诞生&#xff01;今天要谈的是三轴全向机器人&#xff0c;吾理小子是个简单的钢铁直男&#xff0c;争取用最通俗的话语将其运动学讲述清楚&#xff0c;希望对各位道友有帮助。 1.三轴全向机器人背景 什么是三轴…
最新文章