昨天,在写一个支持多线程的字符串hash表时,用来练手的,结果出现了一个内存错误:
HEAP CORRUPTION DETECTED :after Normal block(#63)at 0x00511DA0
昨天晚上,一直调试到两点多,没能搞定,睡在床上反复地想这些指针的指向,指针类型,释放顺序等等,一直没想通,今天早上起来,先把所以变量的地址打印出来,然后对比,依然没发现什么异常,这个错误一直缠绕我到9点多,本来想锻炼自己独立排错能力,确实搞疲了,只好百度吧
在这:http://www.cppblog.com/oyrp/articles/102252.html
最近写了点C++的代码,其中也出现过很多奇怪的错误,heap corruption detected就是其中之一,而且这种错误很容易出现,一般出现该错误,在debug中都有大致如下的错误信息:
heap corruption detected:
after normal block(#xxx) at 0x xxxxxxxx
crt detected that the application wrote to menory after end of heap buffer
这是典型的内存溢出错误,常在内存的delete处发生,而且一般在debug版本中可能出现,release版本中可能并不报错.
出现这个错误的原因一般都是操作new申请的内存溢出,因为在c++中,如果用new分配一段内存,操作的时候改变了该部分的大小,在delete时就会出错.比如说如下部分:
char* p=new char[5];
strcpy(p,"aaaaa");
delete[] p;
这段代码就会出错,因为申请了一个size为5的内存,但是strcpy过去了一个size为6的字符串,因此破坏了这个指针,运行debug版本的时候就会出现先前的错误,但是在release版本中,溢出一个字节的内存很有可能是没有错误的,然后潜在的隐患是肯定存在的,因此,我们在debug遇到这样的错误时候一定要仔细检查对new出的指针的操作.
大概意思是说,我为指针分配的空间不够,造成了内存溢出错误,于是检查指针分配代码,发现了错误,作个记录
我的错误代码
/* node structure */ typedef struct strNode{ char *str; struct strNode *next; }* pstrNode;
定义了这个结构体之后,我想创建一个节点并为之分配空间,最后把它链接到链表上,于是我写下如下代码:/*...*/ pstrNode pnode; if(NULL==(pnode=(pstrNode)malloc(sizeof(pstrNode)))){ st_error("Memory over follow."); } if(NULL==(pnode->str=(char *)malloc((strlen(srcstr)+1)*sizeof(char)))){ st_error("Memory over follow."); } strcpy(pnode->str,srcstr); pnode->next=(*(*(Buckets+id)+hash)); (*(*(Buckets+id)+hash))=pnode; /*...*/就是这段代码出了问题,下面这句if(NULL==(pnode=(pstrNode)malloc(sizeof(pstrNode))))
这里我想开辟一段内存保存一个节点,返回的地址强制转换为指向节点的指针 的类型,即pstrNode类型,所以开辟的空间大小应该是一个节点的大小,而我却只开辟了一个指针的大小 sizeof(pstrNode) 所以,分配的空间不够,后面的写入导致内存溢出了,正确的做法是 sizeof(struct strNode) 即如下代码if(NULL==(pnode=(pstrNode)malloc(sizeof(struct strNode))))
这个内存溢出错误普通运行并并没有明显症状,也能把多写入的东西读出来,但只要一去释放这段内存就崩溃,这是因为额外写入已经破了堆,程序后面的状况不可预测,潜伏着巨大的安全隐患。所以:malloc分配空间,强制转换的是指向后面结构的指针类型 即 (int *p)malloc(sizeof(int)) 中int *p 是指向后面的int的指针。