Debug Assertion Failed _CrtlsValidHeapPointer(block) realloc堆引发的错误
应用场景二级指针的应用中堆的处理问题描述:realloc后出现堆错误#include"algorithm.h"//数组插入元素int insert(int **pp ,int &n,int tmp, int pos){if (0 <= pos&&pos <= n){int *po = *pp;//保存旧 一级指针int *pn=NULL;//创建一级指针作为新地
应用场景
二级指针的应用中堆的处理
问题描述:
realloc后出现堆错误
#include"algorithm.h"
//数组插入元素
int insert(int **pp ,int &n,int tmp, int pos)
{
if (0 <= pos&&pos <= n)
{
int *po = *pp;//保存 旧一级指针
int *pn=NULL;//创建一级指针作为新地址
//pp
cout << "&pp" << "\t" <<&pp<< endl;
cout << "pp" << "\t" << pp << endl;
cout << "*pp" << "\t" << *pp << endl;
cout << "**pp" << "\t" << **pp << endl;
printf("\n");
//po
cout << "&po" << "\t" <<&po << endl;
cout << "po" << "\t" << po << endl;
cout << "*po" << "\t" << *po << endl;
printf("\n");
n =20;
pn = (int *)realloc(po, n*sizeof(int));
//pn
cout << "&pn" << "\t" << &pn << endl;
cout << "pn" << "\t" << pn << endl;
cout << "*pn" << "\t" << *pn << endl;
printf("\n");
pp = &pn;
//pp更新后
cout << "&pp" << "\t" << &pp << endl;
cout << "pp" << "\t" << pp << endl;
cout << "*pp" << "\t" << *pp << endl;
cout << "**pp" << "\t" << **pp << endl;
printf("\n");
//int i = n;
//while (i > pos)
//{
// p[i--] = p[i - 1];//从后往前腾出位置
//}
//p[pos] = tmp;
free(po);
return 0;
}
else
return -1;
}
int main()
{
int n = 9, t, pos = 0;
int *p = (int *)malloc(n*sizeof(int));
int **pp = &p;
scan_arr(p, n);
scanf("%d", &t);
pos = 6;
insert(pp, n, t, pos);
}
运行结果:
原因分析:
报错Expression:_CrtlsValidHeapPointer(block) :这是无效的堆指针,也就是存在堆错误。
free()/delete在一块堆内存的时候会检查堆头,如果堆头有异常,就报堆错误。
对分配的指针不要进行赋值操作了,否则赋值后,再进行free()找不到原来的指针,也会报错。
realloc(p,n)
先判断当前的指针是否有足够的连续空间,如果有,扩大mem_address指向的地址,并且将mem_address返回,如果空间不够,先按照newsize指定的大小分配空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来mem_address所指内存区域(注意:原来指针是自动释放,不需要使用free),同时返回新分配的内存区域的首地址。即重新分配存储器块的地址。
解决方案:
因为realloc重新分配后,po的会自动释放,因此不要重复释放,去掉free(po)便可。
...
n = 100;
pn = (int *)realloc(po, n*sizeof(int));
if (pn)//成功分配
{//旧指针最好清零
po = NULL;//若改为free(po)释放旧指针会导致指针悬空!!!
//free(po);//错误
cout << "po" << "\t" << po << endl; cout << endl;
}
else
{
printf("内存不足\n");
return NULL;
}
//pn
cout << "&pn" << "\t" << &pn << endl;
cout << "pn" << "\t" << pn << endl;
cout << "*pn" << "\t" << *pn << endl;
printf("\n");
...
若无 po=NULL;
而是free(po);
则由于po是个野指针(po指向的块其实已被realloc自动释放,只是po并未清零),这时候对po的操作都是对野指针的操作,没有意义并且可能破坏其他内存;
当n=20较小时,realloc采用第一种分配方式,得到结果如图,虽然堆没有报错,但是*pn不正确,说明pn的块在free(po)的时候冲掉了
当n=100较大时,realloc采用第二种分配方式,运行报错,free(po)会检查堆头,发现po的堆被(realloc自动)释放了,产生堆头错误
因此要使用realloc要特别注意应先判断返回值,再对旧指针清零。
简而言之:free()释放内存并不会将指针置零,可以通过手动置零以免产生野指针。
更多推荐
所有评论(0)