HEAP CORRUPTION DETECTED: after Normal block错误解决方法

目录

前言

一、问题描述

二、原因说明

三、问题案例

总结


前言

        今日在NK网练题,题意为求特殊的倒置字符串,当使用纯C写题解时用到了动态字符数组存储字符串,因为编译器的原因不支持变长数组,所以选用堆区创建动态数组方法解决,但是运行一切正常后加入释放内存模块内容,出现了令人迷惑的 HEAP CORRUPTION DETECTED 异常,经过学习总结,完善个人代码无误后,写出此文,以警醒自身、加深印象。

题目直达链接:倒置字符串


一、问题描述

当我们尝试释放堆区内存时,出现如下问题:

HEAP CORRUPTION DETECTED: after Normal block错误解决方法_第1张图片

二、原因说明

        该问题发生于操作堆内存的时候。产生该问题的原因是:你实际使用的内存大小超出了你实际申请的内存大小,在释放内存的时候就会发生该问题。

三、问题案例

        首先我们方便C/C++使用者的日常习惯,给出两种风格的函数,其作用都是返回动态分配的内存,函数实现如下:

int* use_ptr_c(int n)
{
	return (int*)malloc(n * sizeof(int));
}
int* use_ptr_cplusplus(int n)
{
	return new int[n];
}

给出调用上面两功能的测试函数:

void test()
{
	int* arr1 = use_ptr_c(10);
	int* arr2 = use_ptr_cplusplus(10);
    // 赋值操作
	for(int i = 0;i < 10;i++)
	{
		arr1[i] = i * i;
		arr2[i] = i * i;
	}
    // 打印内容
	for(int j = 0;j < 10;j++)
	{
		printf("%d\t", arr1[j]);
	}
	printf("\n");
	for (int j = 0; j < 10; j++)
	{
		printf("%d\t", arr2[j]);
	}
	printf("\n");
    // 释放内存操作
	free(arr1);
	arr1 = NULL;
	delete[] arr2;
	arr2 = nullptr;
}

运行结果:

接着稍加改动代码,呈现如下:

void test()
{
	int* arr1 = use_ptr_c(10);
	int* arr2 = use_ptr_cplusplus(10);
	for(int i = 0;i <= 10;i++)
	{
		arr1[i] = i * i;
		arr2[i] = i * i;
	}
	for(int j = 0;j < 10;j++)
	{
		printf("%d\t", arr1[j]);
	}
	printf("\n");
	for (int j = 0; j < 10; j++)
	{
		printf("%d\t", arr2[j]);
	}
	printf("\n");
	free(arr1);
	arr1 = NULL;
	delete[] arr2;
	arr2 = nullptr;
}

仔细找不同,发现我们在对堆区数组进行赋值操作时发生了越界访问,对arr1/2[n]元素进行了赋值操作,所以此后当你在释放arr1和arr2指向的内存时,由于你使用了超过申请大小的内存空间,导致内存不能正确释放,就会发生上面的问题

试着运行:

HEAP CORRUPTION DETECTED: after Normal block错误解决方法_第2张图片

不变的味道,果然发生了HEAP CORRUPTION DETECTED异常,那么可能又会想,如果把堆内存释放交给程序垃圾处理模块自动回收,还会发生这样的报错吗?

HEAP CORRUPTION DETECTED: after Normal block错误解决方法_第3张图片

可以看到并没有弹出异常窗口,通过内存泄漏检测工具(VLD),看到有两处内存泄露点,仅仅因为没有对应free和delete对应内存,并非堆区异常。


总结

        当实际使用的内存大小超过了申请内存空间大小时,在以后释放内存的时候就会引发HEAP CORRUPTION DETECTED:after Normal block错误。

解决方案:当申请堆内存空间的时候,申请的空间大小一定要大于等于实际上使用的内存空间大小。

你可能感兴趣的:(个人学习心得(C++),开发语言,c语言,c++)