1. 程式人生 > 其它 >【學習】動態記憶體分配導致的堆溢位問題:Critical error detected c0000374

【學習】動態記憶體分配導致的堆溢位問題:Critical error detected c0000374

今天在寫霍夫曼樹的例程的時候遇到了一個較為棘手的錯誤,在這裡記錄一下

如圖所示,在執行

HT.tree = (HuffmanTree<int>::HTNode*)malloc((m + 1) * sizeof(HuffmanTree<int>::HTNode));

時vs給出了一個奇怪的錯誤,這個錯誤沒有報錯提示,在繼續執行之後繼續顯示

這裡的“堆”代表的是

堆:作業系統有一個記錄空閒記憶體地址的連結串列,當系統收到程式的申請時,會遍歷該連結串列,尋找第一個空間大於所申請空間的堆結點,然後將該結點從空閒結點連結串列中刪除,並將該結點的空間分配給程式,另外,對於大多數系統,會在這塊記憶體空間中的首地址處記錄本次分配的大小,這樣程式碼中的delete語句才能正確的釋放本記憶體空間。 另外由於找到的堆結點的大小不一定正好等於申請的大小,系統會自動的將多餘的那部分重新放入空閒連結串列中。

www.cnblogs.com/George1994/p/6399895.html

換句話說,作業系統給客戶程式用於動態申請和釋放的空間稱為堆。

此處的“堆損壞”就是此連結串列內部的資料檢查不通過,換句話說,裡面的未分配的空間上的值被修改了。由於堆作為連結串列可以隨機訪問,因此對於其訪問域的限制便沒有那麼完善,因而可能在未申請的情況下直接訪問某些不應該訪問的堆的值,此時作業系統分配空閒空間的時候檢查不通過,從而導致堆損壞。

例如下述程式:

int* test_heap_alloc()
{
	int* pTable = new int(256); // 申請一個int結構體變數,初始值為256;
	for (int i = 0; i < 256; i++)
		pTable[i] = i;
	return pTable;
}
int main(int argc, char** argv) {

	test_heap_alloc();
	return 0;
}

https://blog.csdn.net/chunyexiyu/article/details/120233683

(由於vs的intelliSence比較智慧,此處通過RangeChecks即發現了對堆的越界訪問:

0x77E0A37B (ntdll.dll) (CppHomeworkFramework.exe 中)處有未經處理的異常: RangeChecks 檢測程式碼檢測到超出範圍的陣列訪問。

而觀察這段程式,其實這段程式已經成功造成了堆溢位,其關鍵在於對陣列的非法下標訪問。這個下標(自1開始)都沒有申請。


因此解決方案很簡單:檢查已有程式碼,檢視是否存在上述的越界操作。