2015-01-06 49 views
-1

在C++中運行我的代碼時出現問題。我有一個功能和我動態使用這個代碼中定義的二維陣列中它:在C++中釋放數組時發生堆損壞錯誤

double** childs=new double *[2]; 
for(int i=0;i<2;i++) 
    childs[i]=new double[node]; 

的代碼工作良好,直到我決定解除分配該陣列在功能結束時,我使用以下代碼:

for(int i=0;i<2;i++) 
    delete []childs[i]; 

delete [] childs; 

增加的這部分代碼後,我有問題,運行時和出現一個調試錯誤,如下圖所示:

enter image description here

我搜查了很多,但我沒有弄清楚問題所在。我知道這個錯誤是爲了部分解除分配,因爲當我刪除那部分代碼時效果很好。

任何人都可以幫助我嗎? 非常感謝

+2

A因爲沒有大括號而沒有縮進,所以你在問問題。 – Borgleader

+2

你可能寫出了分配數組的界限。或者其他一些陣列。 –

+1

['std :: array'](http://en.cppreference.com/w/cpp/container/array)和['std :: vector'](http://en.cppreference)有什麼問題? COM /瓦特/ CPP /容器/載體)? –

回答

1

沒有足夠的代碼來確定內存被覆蓋的位置,但是您可以通過插入將打印所有指針值的打印語句在程序中找到這個位置。

例如

std::cout << childs << std::endl; 
std::cout << childs[0] << std::endl; 
std::cout << childs[1] << std::endl; 

或者你可以嘗試以下

std::cout << (void *)((char *)childs - sizeof(int)) << std::endl; 
std::cout << (void *)((char *)childs[0] - sizeof(int)) << std::endl; 
std::cout << (void *)) (char *)childs[1] - sizeof(int)) << std::endl; 

或者你可以使用一個循環輸出的孩子的[0]和孩子的[1]在循環:)。

2

「我知道這個錯誤是爲了部分解除分配,因爲當我刪除那部分代碼時效果很好。」 - >這不一定是真的。如果你混淆了記憶,事情可能會在意想不到的地方破裂。例如,可能在代碼的某個時刻,您正在寫入數組之外,然而,當它嘗試刪除[]時會中斷。

1

問題是您的代碼已寫入分配空間的「保護字節」,並且您的Visual C++應用程序的調試版檢測到您這樣做了。

什麼是「保護字節」?它們是在分配空間之前和之後用信息寫入的字節,並由運行時初始化爲某個值。當需要釋放內存時,運行時會檢查這些保護字節以查看值是否已更改。如果它們發生了變化,那麼你在某處錯誤地將數據寫入這些字節佔用的區域的地方出錯了。

Visual C++運行時無法在運行時檢測您寫入防護字節的時間。它只能在釋放完成時檢測到。這就是爲什麼你認爲你的程序「工作正常」,而事實上,它不能正常工作。

因此,通過檢查數組索引中是否存在超出數組範圍的負值或正值來尋找覆蓋。

2

你真正想要做的是匆忙到微軟的網站,並抓住Windows的調試工具。我會等待...

對pageheap選項使用gflags。請參閱http://msdn.microsoft.com/en-us/library/windows/hardware/ff549561(v=vs.85).aspx

Pageheap將更改您的進程的分配程序,並在每次分配之前和之後放置受保護頁面,以及釋放塊。這樣做的結果是,您將能夠檢測何時通過頁面錯誤訪問分配數據的邊界。

很明顯,您想在調試器下運行您的應用程序來捕獲該錯誤並找出錯誤的原因。另外,請注意最好使用發佈版本來完成此任務,因爲調試版本的內存分配周圍將沒有頁堆保護,所以在測試時可能會得到錯誤的負面信息。

祝你好運!