C语言学习笔记---动态内存分配

x33g5p2x  于2022-02-16 转载在 其他  
字(1.7k)|赞(0)|评价(0)|浏览(375)

数组在内存中时存储在连续的位置上,当声明一个数组的时候,编译器就会在内存中分配它所需要的空间,但是有时候还需要使用动态内存为数组分配空间。

比如现在要同统计一个班级学生的成绩,可以申请一个固定大小的数组,但是班级学生的人数时会变动的,当这个固定大小的数组设置的太小时,有可能不能完全放下所有学生的数据,当这个数组设置的太大时,不一定每次每次都能用到这么大的空间。导致系统空间的浪费。

为了使程序更加灵活,同时更加有效的利用内存空间,通常使用动态内存分配来解决这个问题,C库函数里面提供了两个函数mallocfree,一个用来申请内存,一个用来释放内存。这两个函数都在头文件 stdlib.h 中包含。

void *__cdecl malloc(size_t _Size);
  
  void __cdecl free(void *_Memory);

malloc函数用来申请内存空间,它的参数就是需要分配的内存字节数,如果内存中的空间可以满足这个需求,malloc 就会返回一个指向分配的内存块起始位置的指针。如果内存中的空间无法满足这个需求,malloc 就会返回一个NULL指针。

malloc所分配嗯是一块连续的内存。如果请求它分配100个字节的内存,那么这100个字节在内存中就是连续的,它并不会将不同块的内存组合成一块内存来分配。

当使用完内存块之后,必须使用free函数来释放所分配的内存,free 的参数要么是NULL,要么是malloc函数返回的地址指针值。

下面通过一个简单的例子来演示一下动态内存的使用。

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv) 
{
	int *pi;
	int i,j;
	
	printf("请输入需要分配的内存大小:");
	scanf("%d",&i);
	
	pi = malloc(i);
	if(pi == NULL)
	{
		printf("内存分配失败!\n");
		exit(1); 
	}
	printf("\r\n内存分配成功:");
	for(j=0;j<i;j++)
	{
		pi[j] = j;
	}
	for(j=0;j<i;j++)
	{
		printf("%d ",pi[j]);
	}
	
	printf("\r\n\r\n释放内存!\r\n");
	free(pi);
	
	return 0;
}

首先通过键盘输入一个数字,用来确定需要分配的内存大小,然后使用 malloc 函数动态分配内存,内存分配成功后,给内存中填充数字然后将数字打印出来,数字打印完成后就不在需要内存了,此时调用 free 函数释放刚才分配的内存。

程序运行结果如下:

如果内存使用完成之后没有及时释放,那么此块内存在系统中就会一直存在,并且也不能被重新使用,这样随着程序的运行系统中的内存就会越来越少,最后导致系统奔溃。这个过程有一个专业名称叫做内存泄露

使用动态分配内存可以有效的利用内存空间,但是它也不是没有缺点,动态分配内存会产生内存碎片

那么为什么会产生内存碎片呢,这里使用一个简单的例子来说明一下。比如在此时系统动态申请了两次内存分配,每个内存的大小都是10。内存分配的情况如下:

当第一个内存空间使用完成后,代码释放了内存。这样在内存中就有了10个空闲的位置。

此时又有程序申请了8个内存,这时系统就会在刚才释放的空间中重新分配8个给当前程序。

这时候在内存中就会留出来2个空闲的内存,如果刚好有程序需要2个大小的内存,那么这块内存就会被利用上,但是由于2个内存太小了,很难有机会在被利用上,那么这两个空间的内存就会永远的被留在这里。当程序运行时不停的申请释放内存,而每次申请内存时,内存空间必须是连续的,那么这些小的空闲内存就不会被使用到,就产生了内存碎片。程序运行的越久,产生的内存碎片就会越多。

当电脑使用比较久的时候,对硬盘进行碎片整理,就会看到硬盘的内存的存储情况。从图中就可以明确的看出,在内存中未使用的的小块空闲内存占了很大一部分。

相关文章