动态内存分配 - C语言


前言

动态内存分配

提示:以下是本篇文章正文内容,下面案例可供参考

一、为什么要进行动态内存分配

对于静态内存

数组的长度必须事先指定,而且只能是常量,不能是变量,
如果一开始设定太大,存入数据可能后面的空间空很多,太小有可能导致存不下
而且对于数组所占内存空间程序员无法手动编程释放,只能在函数运行结束后由系统自动释放
那可不可以让内存空间随我的需要而变大变小,抑或想释放就释放呢?
这就要进行动态内存分配

对于动态内存分配

更灵活,随时手动释放空间

二、如何进行动态内存分配

四个函数

开辟空间 - 堆区

  1. malloc
  2. realloc
  3. calloc

回收空间

  • free

头文件均为 #include <stdilb.h>
在堆区开辟空间
在这里插入图片描述


malloc

// malloc
//库函数形式: void *malloc( size_t size ); 
//()内为想要开辟的空间总字节大小
// 失败返回NULL,成功返回开辟空间的首地址
#include <stdlib.h>
int main(void)
{
	//开辟10个整型的空间在堆区
	int* p = (int*)malloc(10 * sizeof(int));
	if (p == NULL)
	{
		perror("main");
		return 0;
	}
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		*(p + i) = i;
		printf("%d", *(p + i));
	}
	free(p);
	//归还堆区上的空间
	p = NULL;
	//主动设置p为NULL
	return 0;
}

开辟失败:

在这里插入图片描述


calloc

代码如下(示例):

// calloc
//void* calloc(size_t num, size_t size);
//与malloc不同的一点:calloc会将开辟的内存初始化为0
int main(void)
{
	int* p = calloc(10, sizeof(int));
	if (p == NULL)
	{
		return 1;
	}
	free(p);
	p = NULL;
	return 0;
}

特别:开辟空间的同时将开辟的内存初始化为0


realloc

// realloc - 可以将内存进行灵活调整
//void* realloc(void* memblock, size_t size);
int main(void)
{
	int* p = (int*)calloc(10,sizeof(int));
	if (p == NULL)
	{
		perror("main");
		return 0;
	}
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		*(p + i) = i;
		printf("%d", *(p + i));
	}
	//调整空间大小为20
	int* tmp = realloc(p, 20 * sizeof(int));
	if (tmp != NULL)
	{
		p = tmp;
	}
	free(p);
	//归还堆区上的空间
	p = NULL;
	//主动设置p为NULL
	return 0;
}

最为关键的一个函数:可以灵活调整内存

在这里插入图片描述

在这里插入图片描述


回收空间 - free

回收堆区的空间

void free( void *memblock );
错误示范
int main()
{
	//错误
	int arr[10];//在栈区上开辟的空间
	int* p = arr;
	free(p);
	return 0;
}
正确形式上文都有涉及

当free参数为NULL时,无空间释放


常见动态内存分配问题

常见动态内存的错误
1.NULL指针解引用
int main(void)
{
	int* p = (int*)malloc(10000000000000000);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		*(p + i) = i;
	}
	return 0;
}
2.越界访问
int main(void)
{
	int* p = (int*)malloc(10 * sizeof(int));
	if (p == NULL)
	{
		return 1;
	}
	int i = 0;
	for (i = 0; i <= 40; i++)
	{
		*(p+i) = i;
	}
	return 0;
}
3.用free释放非动态开辟的空间
int main(void)
{	
	int arr[10] = { 0 };
	int* p = arr;
	free(p);
	p = NULL;
	return 0;
}
4.使用free释放动态内存中的一部分
int main(void)
{
	int* p = (int*)malloc(10 * sizeof(int));
	if (p == NULL)
	{
		return 1;
	}
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		*p++ = i;
	}
	//此时p不在指向起始位置了
	free(p);
	p = NULL;
	return 0;
}
5.多次释放同一动态内存空间
int main(void)
{
	int* p = (int*)malloc(100);
	free(p);
	free(p);
	return 0;
}
6.动态开辟空间忘记释放
void test()
{
	int* p = (int*)malloc(100);
	if (p == NULL)
	{
		return;
	}
}
int main(void)
{
	test();
	//函数调用结束后,p作为局部变量被销毁,找不到malloc开辟的空间了
	//对于不停运存的服务器,其造成内存泄漏
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值