cpp:c语言动态分配空间的常见问题

本文详细解析了malloc和free操作后指针管理的两个常见问题:未释放内存就赋值NULL和重复释放内存。讲解了悬空指针的危害,以及为何在free后赋值NULL的重要性和避免重复释放内存的方法。通过实例演示,强调了正确使用和清理动态内存的必要性。
摘要由CSDN通过智能技术生成

_BLOCK_TYPE_IS_VALID(pHead->nBlockUse 报错的两种情况
这个问题是新手容易犯的问题,一定要注意,一个malloc ,用完之后紧接着用一个free,然后赋值 NULL ,一步也不能少。
比如:

int  *p=(int *)malloc(4);
int a[2]={1,3};
p=a;
free(p);
p=NULL;

这个代码,实际上,malloc 后 p 已经有了一个地址了(建议自己打断点看看),而且分配好内存了;此时用a的地址赋值给p,那么p原来的地址就找不到了,这个时候free(p)就找不到要释放的内存,报错。

int  *p=(int *)malloc(4);
free(p);
p=NULL;
int a[2]={1,3};
p=a;
cout<<p[0]<<p[1]<<endl;
free(p);//这里会报错
p=NULL;

这个代码实际上是没有理解一个malloc对应一个free的精髓的所在。
可是既然已经前面已经free(p)了,为什么后面还是可以赋值呢?
因为p本质是还是指针,它可以被赋值。这就造成了似乎系统里还有p的动态分配内存的幻觉,实际上那个内存已经被释放了,再释放第二次自然会报错。
如果还想再用这个p,还要再次为其分配内存,再次分配内存的时候,编译器会在上次的指针指向的位置再次分配内存:

int* p = (int*)malloc(4);
	p[0] = 1;
	cout << p << endl;
	free(p);
	cout << p << endl;
	p = NULL;
	p = (int*)malloc(4);
	free(p);
	cout << p << endl;

输出的三个值相等。

但是实际上,当指针赋值给NULL 之后、就找不到之前对应的位置了。所以
如果在上文 p = NULL;之后加上cout<<p[0]<<endl;

会报错:
引发了异常: 读取访问权限冲突。
p 是 nullptr

所以说为什么会出现上面三个数字都相等的情况、我不太清楚。可以理解为编译器所为。

细心的朋友们可能会问为什么free() 之后都要 给指针赋值 NULL呢?
每次free()完之后都要赋值给NULL 的重要性1,避免出现悬空指针。
什么是悬空指针呢?看下例子:

	int* p = (int*)malloc(4);
	p[0] = 1;
	cout << p[0] << endl;
	free(p);
	cout << p[0] << endl;

在free()之后,第二个cout仍然可以输出一个值:free()之后、指针仍然是指向该位置,输出该位置的值。这就是悬空指针。
在每次free()完之后赋值 NULL 还有一个重要性2:

	int* p = (int*)malloc(8);
	free(p);
	//p = NULL;
	free(p);
	free(p);

这个代码会报错,因为重复释放了内存,但是如果去掉注释、就不会报错了。
原来当 free()的时候,会自动检测该指针是否是NULL,如果是的话,就不进行释放操作了、这样就避免了重复释放内存的错误,文章最开始出现的错误都不会出现了,所以大家要养成free()之后立刻赋值 NULL 的好习惯。

说到这里,提到一个很有趣的事情,看看下面两段代码:

	int* p = (int*)malloc(2*sizeof(int));
	//cout << p [0]<< endl;
	p[0] = 1;
	p[1] = 2;
	//p[2] = 3;
	//p[3] = 4;
	free(p);
	p=NULL;
	int a[2];
	a[0] = 1;
	a[1] = 2;
	//a[2] = 3;

第一个代码、取消注释之后,直到赋值到p[3]的时候、依然不会报错,只有当free(p)的时候才会报错:after Normal block(#165) at … 这句话的代码意味着你修改了分配的内存之外的内容。
第二个代码,取消注释之后,一旦赋值了a[2]就会直接报错;直接告诉你:Stack around the variable ‘a’ was corrupted…

作为指针、不能修改其分配的内存外面的内容,但是可以访问外面的内容。

	int a[2];
	a[0] = 1;
	a[1] = 2;
	cout<<a[100]<<endl;

比如这种,就不会报错。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值