一:問題描述:
出現的問題如下:
二:問題產生的原因說明
該問題發生於操作堆內存的時候。產生該問題的原因是:你實際使用的內存大小超出了你實際申請的內存大小,在釋放內存的時候就會發生該問題。
舉個例子:假如你申請了3個字節的堆內存空間 char *ptr = (char *)malloc(sizeof(char)*3);
但是你在使用的時候使用了4個字節,char *t1 = "abc";// 注意末尾有一個'\0'字符
strcpy(ptr, buf);// 拷貝函數默認會在末尾添加一個'\0'字符,在此處你僅僅申請了3個字節的空間,但你實際使用的空間為4個字節
在往ptr指向的3個字節的堆內存空間,寫入超過一個字節的內容時, vs2010中的編譯器並不會報錯, 但是為后面的內存釋放埋下個巨大的隱患。
此后當你在釋放ptr指向的內存時,由於你使用了超過申請大小的內存空間,導致內存不能正確釋放,就會發生上面的問題。
三:舉例
有問題代碼如下:
1 #define _CRT_SECURE_NO_WARNINGS 2 #include <iostream> 3 using namespace std; 4 int main() 5 { 6 const char* t1 = "abc"; 7 cout << sizeof(t1) << endl; // 4 8 9 // 申請內 10 int memSize = 3; 11 char* ptr = (char*)malloc(sizeof(char) * memSize); // 僅僅申請了3個字節的堆內存空間 12 // 初始化內存 13 memset(ptr, 0, memSize); 14 // 拷貝內容 15 strcpy(ptr, t1); // strcpy拷貝時末尾默認會添加一個'\0'字符, 所以實際使用的內存空間為4個字節,超出了申請的內存空間大小,為后來的內存釋放埋下了巨大的隱患 16 17 cout << ptr << endl; 18 19 if (ptr != NULL) 20 { 21 free(ptr); 22 ptr = NULL; 23 } 24 25 system("pause"); 26 return 0; 27 }
上面的代碼運行后就會出現下面的問題
正確代碼:
1 #define _CRT_SECURE_NO_WARNINGS 2 #include <iostream> 3 using namespace std; 4 int main() 5 { 6 const char* t1 = "abc"; 7 cout << sizeof(t1) << endl; // 4 8 9 // 申請內 10 //int memSize = 3;// 申請內存的大小必須與實際使用的內存大小一致 11 int memSize = 4;// 實際使用的內存大小為4個字節,那么申請內存必須大於等於實際使用的內存。 12 char* ptr = (char*)malloc(sizeof(char) * memSize); 13 // 初始化內存 14 memset(ptr, 0, memSize); 15 // 拷貝內容 16 strcpy(ptr, t1); 17 18 cout << ptr << endl; 19 20 if (ptr != NULL) 21 { 22 free(ptr); 23 ptr = NULL; 24 } 25 26 system("pause"); 27 return 0; 28 }
四:總結
當實際使用的內存大小超過了申請內存空間大小時,在以后釋放內存的時候就會引發HEAP CORRUPTION DETECTED:after Normal block錯誤。
解決方案:當申請堆內存空間的時候,申請的空間大小一定要大於等於實際上使用的內存空間大小。