ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

动态内存管理

2021-10-03 13:01:32  阅读:145  来源: 互联网

标签:malloc 管理 int free 内存 动态内存 size


文章目录

1、动态内存分配的意义

在我们平时定义一个变量或一个数组时其大小为固定值。无法做到灵活多变,我们使用动态内存分配可以很好的解决问题。

2、动态内存函数

2.1malloc

void* malloc (size_t size);

其中size为需要申请的字节大小数,类型为size_t;
返回值为void* 成功时,指向函数分配的内存块的指针。此指针的类型始终为void*,可以将其转换为所需的数据指针类型,如果函数未能分配请求的内存块,则返回空指针。
在我们使用动态内存分配函数后,申请得到的内存要释放这里我们使用 :

void free (void* ptr);

来释放获得的内存。
举一个使用的例子。

#include<stdlib.h>
#include<stdio.h>
int main()
{
	int *p = (int *)malloc(10 * sizeof(int));
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		p[i] = i;
	}
	for (i = 0; i < 10; i++)
	{
		printf("%d ", p[i]);
	} 
	printf("\n");
	free(p);
	return 0;
}

2.2calloc

void* calloc(size_t num,size_t size);
为num元素数组分配一个内存块,每个元素的大小为字节长,并将其所有位初始化为零。有效的结果是分配(num*size)字节的零初始化内存块。如果大小为零,则返回值取决于特定的库实现(它可能是空指针,也可能不是空指针),但不应取消对返回指针的引用。

#include<stdlib.h>
#include<stdio.h>
int main()
{
	int *p = (int *)calloc(10, sizeof(int));
	if (p == NULL)
	{
		return 1;
	}
	return 0;
}

在这里插入图片描述

我们通过查看内存可以看到申请得到的空间确实被初始化为0。

2.3realloc

在我们通过动态内存申请获得内存不够用时,可以使用realloc为其增加空间,其原型为

void* realloc (void* ptr, size_t size);
ptr为指向以前使用malloc、calloc或realloc分配的内存块的指针。或者,这可以是一个空指针,在这种情况下,将分配一个新块(就像调用了malloc一样)。
size为内存块的新大小,以字节为单位。size_t是无符号整数类型。

#include<stdlib.h>
#include<stdio.h>
int main()
{
	int *p = (int *)malloc(10 * sizeof(int));
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		p[i] = i;
	}
	int *c = (int *)realloc(p, 20 * sizeof(int));//扩大容量
	/*if (c != NULL)
	{
		p = c;
	}
	*/
	for (i = 10; i < 20; i++)
	{
		c[i] = i;
	}
	for (i = 0; i < 20; i++)
	{
		printf("%d ", c[i]);
	} 
	printf("\n");
	free(c);
	return 0;
}

这里需要说明当内存中有足够的连续空间时则,分配向后的连续空间返回原指针。当连续空间不足时则会重新找一块新内存,将原来的数据复制下来,新的空间也可以使用。

3、 常见的动态内存错误

3.1 对NULL指针的解引用操作

若动态内存申请1失败则会返回空指针,此时对其解引用就会发生错误。

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

int main()
{
	int *p=(int*)malloc(10* sizeof( int));
	int i = 0;
	for (i = 0; i < 13; i++)//对动态内存分配的空间越界访问。
	{
		p[i] = i;

	}
	free(p);
	return 0;
}

3.3 对非动态开辟内存使用free释放

int main()
{
	int p = 0;
	free(p);//对非动态开辟内存使用free释放
	return 0;
}

3.4使用free释放一块动态开辟内存的一部分

void text()
{
	int *p = (int *)malloc(10 * sizeof(int));//对一部分动态内存申请的释放。
	p++;
	free(p);

}

3.5 对同一块动态内存多次释放

void text()
{
	int *p = (int *)malloc(10 * sizeof(int));//对动态内存的多次释放。
	free(p);
	free(p);

}

3.6 动态开辟内存忘记释放

虽然程序结束会自动释放,但在大项目中可能会造成严重的内存浪费。

4、 柔性数组

下边是一个柔性数组。

struct student
{
	int i;
	int a[];//也可写为a[0]
};

4.1柔性数组的特点与使用

结构中的柔性数组成员前面必须至少一个其他成员。
sizeof 返回的这种结构大小不包括柔性数组的内存。
包含柔性数组成员的结构用malloc函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。

struct student
{
	int j;
	int a[];//柔性数组
}a;
int main()
{
int i = 0;
struct student *p = (struct student*)malloc(sizeof(a)+100 * sizeof(int));//这样相当于a[100]
p->j = 100;
for (i = 0; i<100; i++)
{ 
	p->a[i] = i;
}
free(p);
return 0;


}

4.2 柔性数组的优势

柔性数组对于动态内存申请来说有以下两个优势
1.方便内存释放
如果我们的代码是在一个给别人用的函数中,你在里面做了二次内存分配,并把整个结构体返回给用户。用户调用free可以释放结构体,但是用户并不知道这个结构体内的成员也需要free,所以你不能指望用户来发现这个事。所以,如果我们把结构体的内存以及其成员要的内存一次性分配好了,并返回给用户一个结构体指针,用户做一次free就可以把所有的内存也给释放掉。
2.这样有利于访问速度.
连续的内存有益于提高访问速度,也有益于减少内存碎片。

标签:malloc,管理,int,free,内存,动态内存,size
来源: https://blog.csdn.net/mianhuicai/article/details/120591740

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有