heap corruption detected: after normal block(#121) at 0x01381eb0.
CRT deleted that the application wrote to memory after end of heap buffer
检测到堆损坏:在0x01381eb0的正常块(#121)之后
CRT删除了应用程序在堆缓冲区结束后写入内存的内容
解决方案,把内存开辟的大一点,因为你对不该存在的位置进行了赋值,多发生在边界处理等时候,看看是删除哪一个指针时出现的错误,然后把这个指针相关地址内容的操作都看一遍,同时有时候可能不是这个指针出错,而是别的指针进行了越界操作,恰好影响了这个指针的内容
堆
程序四区 代码区,堆区,栈区,数据区
new malloc 开辟的内存是在堆区,指针p在栈区,栈区当运行结束时,系统进行删除,所以在栈区的使用时,我们很喜欢指针越界,数组越界用于方便访问,结束等操作(然后频出bug)。而堆区运行结束时,系统不进行自动释放,只能人为手动释放,p所开辟的内存空间只能手动释放。
堆损坏
有一个独立于堆内存的变量
当我们越界赋值的时候,这个变量会去检测,当发现规定地址外里面的内容有变化的操作,就会认为堆损坏
vs2013中,多次断点看内存,发现一个现象
int *p=new int【12】; 12*4个字节内容为cd(默认,跟所在位置有关) 然后跟着4个 fd,8个ab,2个 ee fe ,8个00,之后是一串不规律,不确定的数字 共16字节,在之后就是ee fe 正常的默认堆区值
前12*4字节为保存的数据内容,但是后面的 fd ab eefe 00 等没有变过
只要p【12】赋值还是如p【20】赋值,之后在delete时都会出现
heap corruption detected: after normal block(#121) at 0x01381eb0.
CRT deleted that the application wrote to memory after end of heap buffer
然后测试连续开辟两个,内存为段页式存储,当p1和p在同一段时
int *p=new int[12]; int *p1=new int[12]; 这两个一起,(中间加一个int a=1 并不会影响p和p1的地址关系)p1的结尾同上,但是p的结尾fd ab eefe 00都正常 ,然后跟12字节不正常数值然后是28个规律的值00 00 00 00 00 00 00 00 00 00 00 00 30 00 00 00 01 00 00 00 7e 00 00 00 fd fd fd fd然后就是p1
即p【28】为p1【0】
此时p【12】=1,然后释放,会发现运行会卡一会,但是没有影响正常后面操作,但是断点调试会提示 触发断点
然后 p【40】=1(p1越界),先释放p再释放p1 就会出现,其中地址为p1的首地址
heap corruption detected: after normal block(#121) at 0x01381eb0.CRT deleted that the application wrote to memory after end of heap buffer
但是先释放p1,后释放p就没有任何错误
然后再测试p【60】=1(不管是哪个,反正肯定不是正常空间)
发现释放先后顺序改变,都不会出现报错
以上为简单测试,就是直接在main里面,不进行任何操作,直接释放那种,骚操作好玩,但是不要用,吓唬新人还是可以的。改变释放顺序并不是解决方案,只是说改变先后顺序有时候可能不再报错,并不代表你前面的代码都是安全的
正常块(#121)
可以理解为代码段的标号,比如函数func和main,在不同函数里出错,会显示出错函数的块号,换言之,#121在哪个运行代码段,0x01381eb0 的这个地址出现了错误
删除了应用程序在堆缓冲区结束后写入内存的内容,相当于检测到你的堆溢出了,不释放不会出错,但是这块堆区一直被占用,如果占用太多,电脑就会很卡,释放就只能重启电脑,释放的话就会告诉你删除了它不该删除的东西,比如缓冲区
缓冲区 可以简单理解为 键盘--》缓冲区---》内存某部分--》计算---》内存某部分---》缓冲区---》显示,所有内容都在缓冲区,删错了可能就出事了,比如黑屏,突然关机