C语言动态内存分配malloc,calloc,realloc和释放空间free

本文详细介绍了动态内存分配函数malloc, calloc, realloc和释放函数free的使用方法、区别,以及如何避免常见的内存错误,如空指针引用、越界访问和内存泄漏。通过实例演示了内存管理的正确实践。
摘要由CSDN通过智能技术生成

动态内存分配malloc,calloc,realloc和释放空间free


动态内存开辟函数

malloc()函数

函数原型:

void* malloc(size_t size);

头文件:

#include <stdlib.h>

malloc函数向内存申请一块连续可用的且大小为size字节的空间
如果开辟空间成功则返回指向这块空间的指针,否则返回一个空指针NULL

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main()
{
	int i, j;
	int* p = (int*)malloc(10 * sizeof(int));//向内存动态开辟10个整形的空间
	if (p == NULL)
	{
		printf("%s\n", strerror(errno));
		//若动态开辟内存失败,则会将一个错误码传递给errno,打印错误码相对应的错误信息
	}
	else
	{
		for (i = 0; i < 10; i++)
		{
			*(p + i) = i;
		}
		for (j = 0; j < 10; j++)
		{
		printf("%d ", *(p + j));
		}
	}
	free(p);//释放动态开辟的空间(也就是将这块空间还给操作系统)
	p = NULL;//并将其置为NULL,为什么呢?因为虽然p指向的这块空间被释放了,但是p存放的还是这块空间的地址
	return 0;
}
输出:
0 1 2 3 4 5 6 7 8 9
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main()
{
	int i, j;
	int* p = (int*)malloc(INT_MAX);//#define INT_MAX 2147483647
	if (p == NULL)
	{
		printf("%s\n", strerror(errno));
		//若动态开辟内存失败,则会将一个错误码传递给errno,打印错误码相对应的错误信息
	}
	else
	{
		for (i = 0; i < 10; i++)
		{
			*(p + i) = i;
		}
		for (j = 0; j < 10; j++)
		{
		printf("%d ", *(p + j));
		}
	}
	free(p);
	p = NULL;
	return 0;
}
输出:
Not enough space

free()函数

函数原型:

void free(void* ptr);//ptr指向一块待释放的空间

头文件:

#include <stdlib.h>

free函数是用来释放动态开辟的内存的
注意:ptr只能指向一块动态开辟的空间或空指针NULL
如果参数ptr指向的空间不是动态开辟的,那free函数的行为是未定义的
如果参数ptr是NULL空指针,则函数什么事情都不做

calloc()函数

函数原型:

void* calloc(size_t num,size_t size);//num个大小为size字节的元素

头文件:

#include <stdlib.h>

calloc()开辟一块num*size字节的空间,并把空间的每个字节都初始化为0
与malloc()函数的区别只在于calloc()会在返回地址之前把申请的空间的每个字节都初始化为0

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
int main()
{
	int* p = (int*)calloc(10, sizeof(int));//calloc向内存申请了一块10*sizeof(int)即40字节的空间
	//并将此空间的每个字节都初始化为0
	int i;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", *(p + i));
	}
	free(p);
	p = NULL;
	return 0;
}
输出:
0 0 0 0 0 0 0 0 0 0

realloc()函数

函数原型:

void* realloc(void* ptr,size_t size);

ptr是要调整的内存地址
size调整后的大小
返回值为调整之后的内存空间的地址
realloc()调整内存空间有两种情况:
1.若是ptr所指向的内存空间的后面还有足够大的空间,则直接在其后追加内存空间,原来空间的数据不发生变化
2.若是ptr所指向的内存空间的后面没有足够大的空间,则realloc()函数会重新找一个内存区域,开辟一块满足需要的空间,并把原来内存中的数据拷贝过来,释放旧的内存空间,最后返回新开辟的内存空间地址
若是堆区没有一块满足需要的空间,则返回NULL

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
int main()
{
	int i, j;
	int* p = (int*)malloc(5*sizeof(int));
	int* ptr = (int*)realloc(p, 40);
	//int* ptr=realloc(NULL,10)等价于malloc(10)
	if (ptr != NULL)
	{
		p = ptr;
	}
	else
	{
		return 0;
	}
	for (i = 0; i < 10; i++)
	{
		*(p + i) = i;
	}
	for (j = 0; j < 10; j++)
	{
		printf("%d ", *(p + j));
	}
	free(p);
	p = NULL;
	return 0;
}

常见的动态内存错误

1.空指针NULL不能解引用,下面操作是错误的

int* p=(int*)malloc(INT_MAX);//p=NULL
*p=20;

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

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main()
{
	int i, j;
	int* p = (int*)malloc(10*sizeof(int));//向内存动态开辟10个整形的空间
	if (p == NULL)
	{
		printf("%s\n", strerror(errno));
		//若动态开辟内存失败,则会将一个错误码传递给errno,打印错误码相对应的错误信息
	}
	else
	{
		for (i = 0; i <=10; i++)
		{
			*(p + i) = i;//当i=10时越界访问
		}
		for (j = 0; j <=10; j++)
		{
			printf("%d ", *(p + j));
		}
	}
	free(p);
	p = NULL;
	return 0;
}

3.对非动态开辟的空间使用free释放

int a=26;
int* p=&a;
free(p);
p=NULL;

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

int *p=(int*)malloc(10);
p++;//p不再指向动态开辟的内存空间的起始位置
free(p);
p=NULL;

5.对同一块动态开辟的内存空间多次释放

int *p=(int*)malloc(10);
free(p);
free(p);
若是以下这种就可以↓:
int *p=(int*)malloc(10);
free(p);
p=NULL;
free(p);

6.对动态开辟的内存空间忘记释放(忘记释放不再使用的内存空间会导致内存泄露)

int* p=(int*)malloc(26);
//动态开辟内存空间后,没有用free(p)释放
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值