2014-10-08 195 views
0

我有一個字節數組,如下所示:C++堆損壞DETECTED - CRT

BYTE* m_pImage; 
m_pImage = new BYTE[m_someLength]; 

而在我的節目數據的各個階段將被複制到該陣列像這樣:

BYTE* pDestinationBuffer = m_pImage + m_imageOffset; 
memcpy(pDestinationBuffer, (BYTE*)data, dataLength); 

但是,當我去刪除我的緩衝區像這樣:

delete[] m_pImage; 

我收到 HEAP CORRUPTI檢測到 - CRT檢測到應用程序在堆緩衝區結束後寫入內存

現在我嘗試了一個簡單的程序來嘗試並複製該錯誤,以幫助我調查發生了什麼。我從下面看到,如果我創建了一個大小爲5的數組,但是在它的末尾寫下並嘗試刪除它,我會得到完全相同的錯誤。

int* myArray = new int[5]; 
myArray[0] = 0; 
myArray[1] = 1; 
myArray[2] = 2; 
myArray[3] = 3; 
myArray[4] = 4; 
myArray[5] = 5; // writing beyond array bounds 

delete[] myArray; 

現在我的問題是我怎麼可能調試或找出什麼是覆蓋我原來的緩衝區。我知道某些東西會覆蓋緩衝區的末尾,所以有沒有辦法讓visual studio幫助我輕鬆地進行調試。

上面那個複製到數據緩衝區的代碼在刪除之前會被調用幾次,所以很難保持m_pImage內容和複製到它的數據的跟蹤。 (其大約2M價值的數據)

+1

你可以使用像valgrind這樣的工具來找到錯誤。你也可以檢查'm_imageOffset + dataLength <= m_someLength'。從根本上說,你付出的代價是使用原始數組而不是'std :: vector'。 – 2014-10-08 19:25:05

+3

'm_pImage + m_imageOffset + dataLength'將會是'> m_someLength' – 2014-10-08 19:25:27

+0

在visual studio中有內存斷點,你可以嘗試在緩衝區的最後設置一個 – PeterT 2014-10-08 19:25:34

回答

2

現在我的問題是我怎麼可能調試或找出什麼是覆蓋我原來的緩衝區。

我建議儘可能使用assert()聲明。在這種情況下應該是:

BYTE* pDestinationBuffer = m_pImage + m_imageOffset; 
assert(dataLength + m_imageOffset <= m_someLength); 
memcpy(pDestinationBuffer, (BYTE*)data, dataLength); 

然後編譯到調試模式並運行。這種方法的好處 - 在釋放模式下,不會評估任何斷言。

+0

當然,它會更清潔地使用'std :: vector'並避免重新發明輪子 – 2014-10-08 19:39:23

+0

@DavidHeffernan其實我懷疑'std :: vector'會有助於這種情況,'std :: vector'中的數據會去超出界限完全一樣的方式,如果邏輯錯誤不會被修復 – Slava 2014-10-08 19:42:12

+0

調試MSVC運行時有界限檢查'std :: vector',除非我誤認爲 – 2014-10-08 19:43:59

0

堆腐敗是一個難以發現的錯誤。大多數情況下,當報告錯誤時,內存已經被之前執行的一些上游代碼破壞了。如果您決定使用應用程序驗證程序(並且您應該),我還建議您嘗試GFLags and PageHeap。他們是一些額外的工具,允許您設置註冊表標誌來調試這些類型的問題。