动态内存管理

动态内存管理,第1张

介绍动态内存之前先介绍一下内存分区

菜鸡理解的可能不深 希望各位大佬可以执教

全局区

全局区就是存放全局变量和静态变量的以及常量

代码区

代码共享的区域 只能读不能改写的地方

栈区

局部变量 函数形参 呦编译器自动分配和释放

堆区

由 *** 作者自己分配和释放

接下来就介绍动态空间 堆区空间的使用

我们原来开辟的空间都是固定的,创建数组时必须申明数组的大小

但是有时候我们只想输入一个数字根据数字的大小来创建数组或者数字大的一块空间

这时候动态内存就派上用处了

动态内存函数的介绍

c语言提供了动态内存申请函数malloc

使用动态内存函数前先包含头文件

void* malloc(size_t szie);

要注意的是malloc返回值是void*使用时需要我们根据自己需要的类型转换

当malloc函数创建成功时返回一个指向创建好空间的地址

创建失败的时候 返回一个空指针 当我们使用时一定要注意检查

如果size为0 ,malloc的行为是由编译器来决定的 所以我们要避免这种写法

释放动态内存空间函数free

void free(void *);

free注意的点是

free()的参数如果不是指向动态内存,那free的行为是未定义的

free()的参数如果是NULL那将什么都不会发生

举一个例子

#include
#include
int main()
{
	int n;
	int i = 0;
	scanf("%d", &n);
	int* arr;
	arr = (int*)malloc(sizeof(int) * n);
	if (arr == NULL)//判断动态空间是否创建好
	{
		perror("arr");//提示一下动态空间创建失败
		return 1;//如果创建失败程序结束
	}
	//如果创建成功则继续执行
	for (i = 0; i < n; i++)//使用动态内存的数组
	{
		arr[i] = i;
		printf("%d ", arr[i]);
	}
	free(arr);//释放掉创建的动态内存
	arr = NULL;
	return 0;
}

可能有人问 最后一步arr=NULL有没有必要,当然这段代码里是没有必要的 但是我的建议是这样写养成良好的代码习惯 当我们写其他代码时是要创建许多动态内存的 arr=NULL是更保险的做法

c语言还提供了一个函数calloc

calloc使用和malloc是相似的

void* calloc (size_t num, size_t size);

创建num个大小为size的空间,并且把创建好的空间全部初始化为0

所以malloc和calloc区别就在于calloc会把申请的空间全部初始化为0

calloc

 malloc

 还有一个更为灵活的函数realloc

当我们申请的空间大了或者小了 都可以用他来调整空间的大小

void*realloc(void * ptr ,size_t size)
//ptr是要调整内存的地址
//size是调整之后新的大小

realloc调整空间时有两种可能

1.原有地址空间够大的时候

2.原有空间地址不够大的时候

 当情况1的时候要扩展的内存在原有空间后面直接加,不会影响原有空间数据

当情况2的时候要在堆区上找一块合适的大小并且连续的空间使用,带着原有数据一起来到新地址

并返回新地址

我本人给他起了一个外号叫搬家函数 当我们买的东西没把家装满之前我们就一直在这个家 

如果我们买的东西太多把家装满了 我们就带着所以东西搬到新家

动态内存常见的错误

对NULL的解引用

int main()
{
	int n;
	scanf("%d", &n);
	int* arr = (int*)malloc(n);//如果我们不检查他是否为空指针
    //假如n是一个很大的数字动态内存就会申请失败返回NULL
	*arr = 19;
	free(arr);
}

对动态内存越界访问

int main()
{
	int n;
	int i = 0;
	scanf("%d", &n);
	int* arr;
	arr = (int*)malloc(sizeof(int) * n);
	if (arr == NULL)
	{
		perror("arr");
		return 1;
	}
	for (i = 0; i <=n; i++)//注意此时是<=n
	{
		arr[i] = i;
		printf("%d ", arr[i]);
	}
	free(arr);
	arr = NULL;
	return 0;
}

对非动态内存free

int main()
{
  int arr;
 free(arr);
}

只free申请动态内存的一部分

int main()
{
   int *arr;
   arr=(int*)malloc(sizeof(ing)*4);
   arr+2;
   free(arr);//此时arr不在指向内存空间的首位置
   return 0;
}

对一块地址多次free

int main()
{
   int *arr;
   arr=(int*)malloc(sizeof(ing)*4);
   free(arr);
   free(arr);
   return 0;
}

忘记free(会造成内存泄漏)

int main()
{
   int *arr;
   arr=(int*)malloc(sizeof(ing)*4);
   return 0;
}

柔性数组

柔性数组的特点

结构中柔性数组前面至少有一个成员

sizeo返回这个结构大小时不包括柔性数组的大小

typedef struct s1
{
	int a;
	int arr[0];//柔性数组成员
	//如果编译器不支持可以写成arr[];
}s1;
int main()
{
	printf("%d", sizeof(s1));
}

这时打印的值是4

柔性数组的使用

typedef struct s1
{
	int a;
	int arr[0];
}s1;
int main()
{
	s1 * arr1;
	int n;
	scanf("%d", &n);//n为预期柔性数组的大小
	arr1 = (s1*)malloc(sizeof(s1)+sizeof(int)*n);
   if(arr1==NULL)
   {
     return 1;
   }
   free(arr);
	return 0;
}

                               看完如果觉得有帮助  请点个赞吧

 

 

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/567433.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-09
下一篇 2022-04-09

发表评论

登录后才能评论

评论列表(0条)

保存