破开C语言暗夜的第九道光 —— 动态内存管理

一、动态内存函数

  动态内存都是向堆区申请空间,在堆区上进行各种操作。这些函数都包含在头文件 <stdlib.h> 中

malloc

malloc函数:动态开辟内存,但不初始化。

	void* malloc(size_t size);

参数:size 表示的是 要开辟内存的大小,单位是字节(size_t 是无符号整型类型)。

返回类型:malloc函数返回类型是 void* 类型,所以实际使用时要根据情景来强制转换类型,并且需要使用一个指针来接收返回值。

注:malloc 申请内存可能会失败。若malloc 申请内存成功,返回申请的那块内存的首地址;若申请失败,则返回NULL。所以内存申请后,要检验是否申请成功。

free

free函数:释放动态开辟的内存。

	void free(void* ptr);

参数:可以接收任意类型的指针,ptr 表示 那个接收动态内存首地址的指针

返回类型:空类型,无返回值。

注:1、free函数不能用来释放非动态开辟的内存空间。
2、如果参数 ptr 是NULL指针,则free函数不进行任何操作。

malloc 与 free 要搭配使用

int main()
{
	int* p = (int*)malloc(100); //申请了100个字节,即 25个整型
	if (p == NULL)  //判断内存是否申请成功
	{
		printf("Failure\n");
		return 1;
	}

//当这些空间不用了,就要释放掉
	free(p);
	p = NULL;  //为防止野指针,指针释放后要被置空
	return 0;
}

calloc

calloc函数:动态开辟内存,并把内存的每个字节都初始化为0。

	void* calloc(size_t num, size_t size);

参数:num 代表 要申请的元素的数量,size 代表 每个元素的大小(单位字节)。

返回类型:void*,同样需要用指针来接收。

realloc

realloc函数:改变已经申请的动态内存的大小。

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

参数:ptr 是要调整的内存的首地址,size 是调整后的新大小(单位字节)。

realloc 和 calloc 也需要进行检验,判断是否成功。

对于realloc的申请有不同的情况:
  若申请成功有两种情况,第一种是原空间后面有足够的内存,新增的空间直接在后面续上,然后返回旧的地址;第二种是原空间后没有足够的内存用来扩容,那么realloc会寻找一个新的满足扩容后大小的空间,然后把旧空间内的数据拷贝到新空间前面对应的位置上,并把旧空间释放,同时返回新空间的首地址。
  若申请失败,则返回NULL,用原指针来接收可能会导致数据丢失,所以realloc要新建一个指针来接收,不能直接用原指针接收扩容后的内存。

注:realloc接收的指针是空指针时相当于是malloc。

realloc的使用示例:

#include <stdio.h>
#include <stdlib.h>
int main()
{
	int* p = (int*)malloc(16); 
	if (p == NULL)  //判断malloc是否申请成功
	{
		printf("Failure\n");
		return 1;
	}

//用realloc扩容
	int* pa = (int*)realloc(p,40); //用新指针接收,扩容为40字节
	if (pa == NULL)  //判断realloc是否扩容成功
	{
		printf("Failure\n");
		return 1;
	}
	p = pa;  //成功后再把空间赋给原指针
	pa = NULL;
	//用完后释放并指针置空
	free(p);
	p = NULL; 
	return 0;
}

二、常见的动态内存错误

  • 对NULL指针的解引用操作
      出现这种错误,一般是忘记检验内存申请是否成功就直接使用接收的指针。

  • 对动态开辟空间的越界访问
      这个错误要注意的是,三个动态内存申请函数的参数的单位,区分开字节和元素个数,同时注意动态申请的内存与数组类似,首元素从下标0开始。

  • 对非动态开辟内存使用free释放
      free不能用于接收非动态开辟内存的指针。

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

void test()
{
	 int *p = (int*)malloc(100);
	 p++;
	 free(p);//p不再指向动态内存的起始位置
}

  此时释放的就是开辟内存的一部分,所以接收地址的原指针不要随意更改,要更改地址来实现一些功能就新建一个指针,拷贝一下再用。

  • 对同一块动态内存多次释放
void test()
{
	int *p = (int *)malloc(100);
	free(p);
	free(p);//重复释放
}

  同一块动态内存只能释放一次。

  • 动态开辟内存忘记释放(内存泄漏)
      内存泄漏的问题还是很严重的,所以动态开辟的内存一定要及时用free释放,使用了动态内存函数的地方要用注释标注,防止忘记释放。
  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

遥逖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值