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

news2024/11/20 1:40:36

目录

本章重点

        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.coloradmin.cn/o/755888.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Maven的exec插件

Maven的exec插件介绍 利用maven的exec插件可以执行系统和Java程序。 官网资源 exec插件官网&#xff1a;https://www.mojohaus.org/exec-maven-plugin/java-mojo.html Goals exec:exec表示在一个单独的进程内执行系统和Java程序。 exec:java表示在当前的Java虚拟机内执行J…

基于FPGA的一维卷积神经网络算法实现(1D-CNN、BNN的FPGA加速实现)

文章目录 概要网络结构一维卷积介绍&#xff08;科普性质&#xff09;FPGA架构FPGA端口定义操作步骤结果演示总结 概要 本文介绍一种基于FPGA的1维卷积神经网络算法加速实现的方案&#xff0c;其中为了进一步提升运算速度&#xff0c;除了第一层卷积采用的是普通卷积运算&…

带你认识从 “�“ 到 “锟斤拷“ 错误编码

以一首五言绝句作为开篇&#xff0c;你知道背后说的是什么吗&#xff1f; 手持两把锟斤拷 口中疾呼烫烫烫 脚踏千朵屯屯屯 笑看万物锘锘锘 &#xfffd; 为何物&#xff1f; 在前不久石头哥的这篇文章中 —— 你可能也会掉进这个简单的 String 的坑&#xff0c;讲述了因字…

【sgUploadTray】上传托盘自定义组件,可实时查看上传列表进度

【sgUploadTray】上传托盘自定义组件&#xff0c;可实时查看上传列表进度 特性&#xff1a; 可以全屏可以还原尺寸可以最小化可以回到右下角默认位置支持删除队列数据 sgUploadTray源码 <template><div :class"$options.name" :show"show" :size…

架构训练营学习笔记3-5:消息队列备选架构设计实战

本文属于架构训练营学习笔记系列&#xff1a;模块3的案例讲解 总的来说&#xff0c;这篇从更高的维度去讲&#xff0c;而不是关注消息队列的常见问题&#xff1a;比如消息如何发送&#xff0c;消息如何不丢失 &#xff0c;消息如何不重复。总体上分为2部分&#xff1a;利益干系…

LaTex 1【字体、符号、表格】

​&#xff08;上一期已经安装完软件&#xff0c;但是突然出现了一点子问题不会解决&#xff0c;先用overleaf来学习吧&#xff0c;网站还是很给力的&#xff09; 关键字部分&#xff1a; \quad:代表空格【无论你打多少个空格都不是空格&#xff0c;要输入“\quad”】 字体部分…

github进不去的解决办法

github就凭运气进吧&#xff0c;偶尔能进去。 介绍几个可以快速进的办法&#xff1a; 第一个&#xff0c;安装插件&#xff1a;&#xff08;在microsoft搜索watt toolkit插件并安装&#xff09; 然后勾选github选项&#xff1a; 接着返回你github网站就可以了。 第二个&#…

简单工厂模式详解

文章目录 前言一、简单工厂模式定义二、举个例子三、简单工厂模式的缺点总结 前言 本篇我们了解一下简单工厂模式&#xff0c;它是设计模式的雏形&#xff0c;是学习设计模式的开端&#xff0c;我会结合案例说明它的设计思路。 一、简单工厂模式定义 简单工厂模式并不是GoF23…

JSX的基础使用

1. JSX嵌入变量作为子元素的使用 ①当变量是Number、String、Array类型时&#xff0c;可以直接显示&#xff1b; ②当变量是null、undefined、Boolean类型时&#xff0c;内容为空&#xff1b; 若想要展示nul、undefined、Boolean类型&#xff0c;转字符串&#xff1b;转换方式…

堆--二叉树的特有形式

目录 前言1.二叉树的顺序结构及实现1.1二叉树的顺序结构1.2堆的概念及结构 2.堆的功能函数的实现2.1堆结构体的定义2.2堆的初始化2.3堆的插入2.4 获取堆是否为空、堆大小、堆顶元素的函数2.5堆的销毁2.6对利用堆结构数组的数据建堆2.7堆的删除堆结构的源码 3.堆排序建堆的时间复…

2核4G服务器能安装多少个网站?亲测

2核4G服务器能安装多少个网站&#xff1f;2核4g配置能承载多少个网站&#xff1f;一台2核4G服务器可以安装多少个网站&#xff1f;阿腾云2核4G5M带宽服务器目前安装了14个网站&#xff0c;从技术角度是没有限制的&#xff0c;只要云服务器性能够用&#xff0c;想安装几个网站就…

AE关键帧

关键帧 根据上次说到的五大变换&#xff0c;找准起始时间点和起始动作再去找结束时间点和结束动作&#xff0c;其中包括可使用贝塞尔曲线对锚点进行拖拽&#xff0c;使其完成曲线运动 快捷键 n删除右侧&#xff0c;b删除左侧&#xff0c;ctrlshiftd裁剪&#xff0c;ctrld复制…

我记忆中的电脑城

目录 一、我记忆中的电脑城 二、电脑城衰退 三、拥抱趋势 在过去很长一段时间里&#xff0c;想要购买电子设备都逃不开一个叫“电脑城”的地方&#xff0c;那里鱼龙混杂良莠不齐&#xff0c;是令许多人记忆深刻分外难忘之处。 一、我记忆中的电脑城 想起上一次去电脑城&…

ylb-接口11实名认证

总览&#xff1a; 在web模块config包下&#xff0c;创建实名认证的一个配置类JdwxRealnameConfig&#xff1a; package com.bjpowernode.front.config;import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype…

【NI USRP】 USRP 硬件资源和性能是怎么样的呢?是如何构成的呢

B系列 型号频段最大带宽通道FPGAADI 芯片B200mini70 MHZ - 6 GHZ56 MHz1X1Xilinx Spartan-6 XC6SLX150AD9364B200mini-i70 MHZ - 6 GHZ56 MHz1X1Xilinx Spartan-6 XC6SLX75AD9364B205mini-i70 MHZ - 6 GHZ56 MHz1X1Xilinx Spartan-6 XC6SLX75AD9364B20070 MHZ - 6 GHZ56 MHz1X…

AN OVERVIEW OF LANGUAGE MODELS RECENT DEVELOPMENTS AND OUTLOOK

LLM系列相关文章&#xff0c;针对《AN OVERVIEW OF LANGUAGE MODELS: RECENT DEVELOPMENTS AND OUTLOOK》的翻译。 语言模型综述&#xff1a;近年来的发展与展望 摘要1 引言2 语言模型的类型2.1 结构化LM2.2 双向LM2.3 置换LM 3 语言单元3.1 字符3.2 单词和子单词3.2.1 基于统…

Java正则表达式捕获组

捕获组是将多个字符视为一个单元的一种方法。 它们是通过将要分组的字符放在一组括号中来创建的。 例如&#xff0c;正则表达式(dog)创建包含字母d&#xff0c;o和g的单个组。 捕获组通过从左到右计算它们的左括号来编号。 在表达式((A)(B(C)))中&#xff0c;例如&#xff0c;…

Xline 源码解读(一) —— 初识 CURP 协议

01、Xline是什么 Xline 是一款开源的分布式 KV 存储引擎&#xff0c;其核心目的是实现高性能的跨数据中心强一致性&#xff0c;提供跨数据中心的meatdata 管理。那么 Xline 是怎么实现这种高性能的跨数据中心强一致性的呢&#xff1f;这篇文章就将带领大家一起来一探究竟。 02…

GAMES101 OpenCV环境安装

文章目录 Opencv 库编译Step 1.下载源码Step 2. 使用CMake编译Step3. 解决CMake 过程中的报错错误1&#xff1a; 错误的Python版本:错误1 解决办法 错误2&#xff1a;下载ippicv_2020_win_ia32_20191018_general.zip失败错误2 解决办法 错误3&#xff1a;ffmpeg相关文件下载失败…

ROS学习笔记(0):几个重要概念:节点、消息、主题、服务

1、节点&#xff08;node&#xff09; 节点是进行运算任务的进程。一个系统可以由很多节点组成&#xff0c;节点也可以称为软件模块。 ROS是以节点的形式开发的&#xff0c;节点是根据其目的&#xff0c;可以细分的可执行程序的最小单位。 主节点 由于机器人的元器件很多&…