首页 > 系统相关 >动态内存的相关知识点

动态内存的相关知识点

时间:2024-11-09 08:50:23浏览次数:7  
标签:知识点 malloc int free 内存 动态内存 相关 NULL

今天学了动态内存管理的相关知识点,首先什么是动态内存呢,我的理解是可大可小的,能够动态变化的。

1. 为什么存在动态内存分配 我们已经掌握的内存开辟方式有:
int main()
{
	int a = 10;
	int arr[10] = { 0 };
	int n;
	scanf("%d", &n);
	int arr1[n];
	return 0;
}

向上面这些,例如固定写好10个数组,或者利用变长数组的来在栈区开辟空间,但是这种空间大小是固定,就很死板。因此我们可以学习动态内存开辟的方式。而学习动态内存开辟最主要就是学习动态内存开辟的函数。malloc ralloc free跟cealloc这些开辟内存的函数。

2. 动态内存函数的介绍 2.1 malloc free C 语言提供了一个动态内存开辟的函数:
void* malloc (size_t size);
这个函数向内存申请一块 连续可用 的空间,并返回指向这块空间的指针。 如果开辟成功,则返回一个指向开辟好空间的指针。 如果开辟失败,则返回一个 NULL 指针,因此 malloc 的返回值一定要做检查。 返回值的类型是 void* ,所以 malloc 函数并不知道开辟空间的类型,具体在使用的时候使用者自己 来决定。 如果参数 size 为 0 , malloc 的行为是标准是未定义的,取决于编译器 C 语言提供了另外一个函数 free ,专门是用来做动态内存的释放和回收的,函数原型如下
void free (void* ptr);
free 函数用来释放动态开辟的内存。 如果参数 ptr 指向的空间不是动态开辟的,那 free 函数的行为是未定义的。 如果参数 ptr 是 NULL 指针,则函数什么事都不做。
int main()
{
	int* p = (int*)malloc(100);//强制类型转化成整型指针,返回动态开辟内存的起始地址
	if (p == NULL)//判断指针是否为空
	{
		perror("malloc");
		return 1;
	}
	int i = 0;
	for (i = 0; i < 25; i++)
	{
		*(i + p) = i + 1;
	}
	for (i = 0; i < 25; i++)
	{
		printf("%d ", *(i + p));
	}
	free(p);//释放空指针
	p = NULL;//将开闭的起始地址初始化为0
	return 0;
}
2.2 calloc C 语言还提供了一个函数叫 calloc , calloc 函数也用来动态内存分配。原型如下:
void* calloc (size_t num, size_t size);
函数的功能是为 num 个大小为 size 的元素开辟一块空间,并且把空间的每个字节初始化为 0 。 与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全 0 。
int main()
{
	int*p=(int*)calloc(10, sizeof(int));
	if (p == NULL)
	{
		perror("calloc");
		return 1;
	}
	int i = 0;
	for(i = 0; i < 10; i++)
	{
		printf("%d ", *(p + i));
	}
	free(p);
	p = NULL;
	return 0;
}

跟刚刚的malloc非常相似。这些开辟内存的函数要跟free搭配使用,使用完要把起始指针初始化为NULL。

所以如何我们对申请的内存空间的内容要求初始化,那么可以很方便的使用 calloc 函数来完成任务。 2.3 realloc realloc 函数的出现让动态内存管理更加灵活。 有时会我们发现过去申请的空间太小了,有时候我们又会觉得申请的空间过大了,那为了合理的时 候内存,我们一定会对内存的大小做灵活的调整。那 realloc 函数就可以做到对动态开辟内存大小 的调整。 函数原型如下
void* realloc (void* ptr, size_t size);
ptr 是要调整的内存地址 size 调整之后新大小 返回值为调整之后的内存起始位置。 这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到 新 的空间。
#include<stdio.h>
#include<stdlib.h>
int main()
{
	int*p=(int*)malloc(100);
	if (p == NULL)
	{
		perror("malloc");
		return 1;
	}
	int* pr = (int*)realloc(p, 200);//将内存扩大能放50个元素
	if (pr != NULL)
	{
		p = pr;
	}
	int i = 0;
	for (i = 0; i < 50; i++)
	{
		*(p + i) = i + 1;
	}
	for (i = 0; i < 50; i++)
	{
		printf("%d ", *(p + i));
	}
	free(p);
	p = NULL;
	return 0;
}

realloc函数调整动态内存大小的时候会有俩种情况:

情况1:原有空间之后有足够大的空间

情况 2 :原有空间之后没有足够大的空间 情况 1 当是情况 1 的时候,要扩展内存就直接原有内存之后直接追加空间,原来空间的数据不发生变化。 情况 2 当是情况 2 的时候,原有空间之后没有足够多的空间时,扩展的方法是:在堆空间上另找一个合适大小 的连续空间来使用。这样函数返回的是一个新的内存地址。由于上述的两种情况,realloc 的使用就要注意一些 此时,需扩展的空间后方没有足够的空间可供扩展,并且堆区中也没有符合需要开辟的内存大小的空间。结果就是开辟内存失败,返回一个NULL。我们再接收扩容的起始地址的时候就需要新建一个函数指针来接收,扩容的空间是失败返回NULL. 常见的动态内存错误 一对 NULL 指针的解引用操作 如果malloc开辟空间失败,返回空指针,然后对返回的指针进行解引用操作就会导致非法访问
void test()
{
 int *p = (int *)malloc(INT_MAX/4);
 *p = 20;//如果p的值是NULL,就会有问题
 free(p);
}

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

如果malloc开辟10个元素的空间,你偏偏要放11个元素进去,就会导致越界访问。

int main()
{
	int* p = (int*)malloc(40);
	if (p != NULL)
	{
		int i = 0;
		for (i = 0; i <= 10; i++)
		{
			*(p + i) = i + 1;
		}
	}
	return 0;
}

三对非动态开辟的内存使用free释放
free函数只能释放动态开辟的内存空间。

int main()
{
 int*p=20;
free(P);
p=NULL;
return 0;
}

四、使用free释放动态开辟内存的一部分
free函数只能从开辟好的动态内存空间的起始位置开始释放,所以使用free函数释放动态内存时,传入的指针必须是当时开辟内存时返回的指针。

void test()
{
 int *p = (int *)malloc(100);
 p++;
 free(p);//p不再指向动态内存的起始位置
}
五  对同一块动态内存多次释放 、对同一块内存多次释放
对同一块动态内存空间只能释放一次。避免这个问题的出现也很简单,我们只要记住在第一次释放完空间后立即将该指针置为NULL即可,因为当传入free函数的指针为NULL指针时,free函数什么也不做(也就不会出现对同一内存多次释放的问题)。                                                                
void test()
{
 int *p = (int *)malloc(100);
 free(p);
 free(p);//重复释放
}

六动态开辟内存忘记释放(内存泄漏)
一定要做到自己开辟的动态内存自己记得释放,也许你觉得这件事没什么,但当你需要从几十万甚至几百万行代码中找出一个因忘记释放动态内存而造成的内存泄漏问题时,你就会真正知道这件事情要性。                                                                                                                                        

标签:知识点,malloc,int,free,内存,动态内存,相关,NULL
From: https://blog.csdn.net/2402_82552926/article/details/143609096

相关文章

  • 在Windows操作系统中,HKEY_CURRENT_USER\Console 是注册表中的一个键路径,它用于存储与
    在Windows操作系统中,HKEY_CURRENT_USER\Console是注册表中的一个键路径,它用于存储与控制台窗口(例如命令提示符窗口,CMD)的配置和设置相关的数据。以下是HKEY_CURRENT_USER\Console的详细说明:1. 位置路径:HKEY_CURRENT_USER\Console\2. 作用这个注册表项包含了当前用户对控制......
  • 原木、实木和家具是常见的木材相关术语,它们之间有一定的区别,但容易让人混淆。下面我将
    原木、实木和家具是常见的木材相关术语,它们之间有一定的区别,但容易让人混淆。下面我将为你详细解释如何区分这三者以及它们的不同之处,帮助你更好地理解和区分这些概念。1. 原木(RawWood)定义:原木是指直接从树木中砍下来的粗大木材,未经任何加工。它通常是树干或大树枝,外形不规则,......
  • Hive3.1.2搭建文档包含详细步骤及相关截图以及常见问题解决
    hive-3.1.2分布式搭建文档1、下载,上传,解压,配置环境变量#1、解压(解压到上级目录)tar-zxvfapache-hive-3.1.2-bin.tar.gz-C..#2、重名名mvapache-hive-3.1.2-binhive-3.1.2#3、配置环境变量vim/etc/profile#4、在最后增加配置exportHIVE_HOME=/usr/local/......
  • 网络安全知识点梳理(期末不挂科)
    目录第一章漏洞类型一、操作系统漏洞二、网络协议漏洞三、数据库漏洞四、网络服务漏洞第二章 OSI网络安全体系一、OSI参考模型回顾二、OSI网络安全体系第三章 网络安全机制一、网络访问控制二、数据加密与保护三、威胁情报与安全分析四、虚拟化和容器安全五......
  • 监控 Windows 更新补丁安装过程中的文件夹和文件,可以通过 PowerShell 监控 Windows 更
    监控Windows更新补丁安装过程中的文件夹和文件,可以通过PowerShell监控Windows更新的日志文件夹、注册表或其他相关位置。Windows更新会在多个地方生成日志和文件,下面提供了一个使用PowerShell监控Windows更新相关路径、文件夹及文件的示例。监控Windows更新相关的文......
  • web页面引用相关文件或者页面方式汇总
    在网页里包含另一个网页(或文件)方法如下:一、要包含的文件是css文件的话,用<linktype=text/cssrel=stylesheethref=1.css>二、要包含的文件是js文件的话,用<scriptlanguage=javascriptsrc=a.js></script>三、要包含的文件是html文件的话,用<!--#includefile="htmlpage.htm"-......
  • c语言入门学习这一篇就够了-知识点总结(三万字二级必看)
    C语言   C语言是中高级语言的代表之一,它是所有现代编程语言的基石,包括C++、Java、C#、Python、JavaScript、Swift等。C语言是学习其他编程语言的基础,因为它提供了对系统底层的精确控制,这使得它在开发操作系统、驱动程序、嵌入式系统、高性能计算等领域中有着不可替代的......
  • C:\Windows\System32\spp\store 文件夹是 Windows 操作系统中与激活和许可证管理
    C:\Windows\System32\spp\store文件夹是Windows操作系统中与激活和许可证管理相关的一个重要文件夹。该文件夹存储了与Windows激活过程相关的信息、许可证密钥、许可证的状态等数据。具体来说,它主要涉及SoftwareProtectionPlatform(SPP),即软件保护平台。1. 什么是SPP......
  • 密码学知识点整理一:密码学概论
    密码学是什么?密码学是一门研究编制密码和破译密码的技术科学。密码学,作为信息安全的核心技术之一,其重要性在于能够为信息传输提供安全保障,确保数据在存储或传输过程中的机密性、完整性与真实性不被破坏。从古至今,随着科技的发展和计算机技术的广泛应用,密码学已经由最初的......
  • 电蚊拍,所涵盖的知识点,深度解剖!
    更多电路设计,PCB设计分享及分析,可关注本人微信公众号“核桃设计分享”!电蚊拍,想必大家都用过或者见过,特别是夏天一顿“噼里啪啦”的声音,伴随着阵阵“烧焦味”就知道有多少蚊子永诀于此了!网上也有非常多的文章讲解了电蚊拍的工作原理的,但是原理讲解篇幅较少,总感觉少了点什么,看......