动态内存管理

目录

一.malloc和free

1.1 malloc

1.2 free

二.calloc和realloc

2.1 calloc

2.2 realloc

三.常见的动态内存的错误

3.1 对空指针的解引用操作

3.2 对动态内存空间的越界访问

3.3 对非动态内存空间使用free

3.4 使用free释放动态空间的一部分

3.5 对同一块空间多次释放

3.6 对动态空间忘记释放


一.malloc和free

1.1 malloc

malloc的函数原型为:

void* malloc(size_t size);

这个函数向内存的堆区申请一块指定大小的连续可用空间,并返回指向这块空间的指针。
a.如果开辟成功,则返回一个指向开辟好空间的指针。
b.如果开辟失败,则返回一个空指针,因此malloc的返回值一定要做检查。
c.函数的返回值是void *,所以malloc函数并不知道开辟空间的类型,具体使用时自己指定。
d.如果size是0的话,malloc的行为是C语言标准未定义的,取决于编译器。

1.2 free

free是用来释放动态内存空间的,函数原型为:

void* free(void* ptr);

 a.如果参数ptr指向的空间不是动态开辟的,那free函数的行为是会报错的。
b.如果参数ptr是一个空指针,则释放无效。
注意:
1.函数malloc和free所需要的对应的头文件是#include<stdlib.h>。
2.动态内存函数申请的空间是堆区的,而普通变量申请的空间是在栈区。
3.每次申请动态空间后要判断是否开辟成功,否则后果自负。
4.最后一定要将申请的动态空间释放。
5.释放后的指针并不是空的,而是申请前的值,所以我们最后要把他放空。

#include<stdio.h>
#include<stdlib.h>
int main()
{
    float* ptr=(*float)malloc(sizeof(float));//开辟一个浮点型的空间
    if(ptr==NULL)//一定要判断是否开辟成功
    perror("malloc");//用来显示错误
    ......
    free(ptr);//最后释放掉动态空间
    ptr=NULL;
    return 0; 
}

二.calloc和realloc

2.1 calloc

calloc函数也是用来分配内存空间的,函数原型为:

void* calloc(size_t num,size_t size);

a.num是元素个数,size是元素类型所占的字节数。
b. 与malloc不同的是calloc在返回指针前,会把空间初始化为0.
比如:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
int main()
{
	int* p = (int*)calloc(10,sizeof(int));
	if (p == NULL)
	{
		perror("malloc fail!");
		return 1;
	}
	int i = 10;
	while (i--)
	{
		printf("%d ", *p++);
	}
    free(p);
    p=NULL;
	return 0;
}

 这里的结果是10个0,但是如果用malloc那么结果就是10个随机数。

2.2 realloc

realloc函数是用来调整动态空间的大小的,可以调大,也可以调小,其函数原型为:

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

 prt指向要调整的内存空间,size是调整后的新空间大小。
调整空间有两种情况:
a.原有空间之后有足够大的空间

 如图,ptr所指的空间有后又足够的空间,那么调大的空间就会直接追加在原来的空间,函数返回的空间地址跟原地址相同,原来的数据不会发生变化。
b.原有空间之后没有足够大的空间

 当新的空间太大时,原来地址的空间不能容下,realloc函数就会返回一个新的地址,重新开辟一个新的空间,并且自动把原来的数据拷贝到新的空间,然后再自动释放掉原来的空间。
注意:
1.realloc函数的指针形参是指向堆区动态空间的指针,并不是栈区的普通指针。
2.时候用realloc时,由于情况不确定,所以通常用一个新的临时指针来接受realloc的返回值。
使用临时指针的原因:如果使用原指针,若是realloc开辟空间失败,那么会返回一个空指针,造成原指针不再指向原空间,也就找不到到来的数据,造成内存泄漏。

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
int main()
{
	int* p = (int*)calloc(10,sizeof(int));
	if (p == NULL)
	{
		perror("malloc fail!");
		return 1;
	}
	int* ptr;//临时指针
	ptr = (int*)realloc(p, 20* sizeof(int));//使用临时指针接收调整后的空间
	if (ptr== NULL)
	{
		perror("realloc fail!");
		return 1;
	}
	p = ptr;//将新的空间传回来
	free(ptr);
	free(p);
	ptr = NULL;
	p = NULL;
	return 0;
}

三.常见的动态内存的错误

3.1 对空指针的解引用操作

int main()
{
   int *p=(int*)malloc(4);
   *p=20;//没有判断,p可能是空指针
   return 0;
}

3.2 对动态内存空间的越界访问

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
int main()
{
	int* p = (int*)malloc(40);
	for (int i = 0; i <= 10; i++)
	{
		*(p + i) = i;//访问第10个元素的时候的时候,为越界
	}
	free(p);
	p = NULL;
	return 0;
}

3.3 对非动态内存空间使用free

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
int main()
{
	int a = 6;
	int* p = &a;//p不是指向动态空间的指针
	free(p);
	return 0;
}

3.4 使用free释放动态空间的一部分

#include<stdio.h>
#include<stdlib.h>
int main()
{
	int* p = (int*)malloc(20);
	p = p + 2;
	free(p);
	return 0;
}

 free函数释放必须是从空间的起始地址开始释放,不可释放部分。

3.5 对同一块空间多次释放

int main()
{
	int* p = (int*)malloc(20);
	......
	free(p);
	free(p);
	return 0;
}

3.6 对动态空间忘记释放

注意:
malloc//realloc//calloc开辟的内存空间,除非手动free释放或者程序结束,否则被不会释放,将会造成内存泄漏。

  • 27
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值