2014-09-27 33 views
-1

我正在運行一個小示例。我的代碼是瞭解訪問內存中的堆損壞情況

int main() 
{ 
    char * mymem = new char[8]; 
    //1 
    memcpy(mymem+8,"hello",5); //this cause heap corruption 

    //2 
    mymem[32]='a'; //this doesn't cause heap corruption 

    //3 
    delete [] mymem; 

    return 0; 
} 

在上面的代碼,如果我執行1然後我得到堆損壞刪除即3, 但如果再執行2我沒有得到刪除IE 3.我很好奇任何堆損壞要知道爲什麼會發生這種情況,因爲在兩種情況下,我都試圖在分配的內存之外寫入數據。

+1

它們都會導致堆損壞。就是這樣,偶然的情況下,你只會在第一個例子中看到崩潰。 – 2014-09-27 14:51:34

+1

「// 1」和「// 2」都超出邊界訪問權限,這會導致未定義的行爲。它可能會破壞堆棧,或者可能會做其他事情,或者什麼也不做。它沒有定義。 – 2014-09-27 14:52:18

+0

我試圖在Windows和Linux上運行,但在第二種情況下,我沒有得到堆腐敗錯誤 – singh 2014-09-27 14:52:38

回答

2

行爲是未定義的,但我會嘗試回答這個問題,並解釋爲什麼在這種情況下,第一次訪問會得到堆損壞,但第二次訪問沒有堆損壞。

當您調用new[]new時,某些運行時庫將分配更多的內存而不是爲了使用額外內存而需要的內存數量爲guard bytes。額外內存的數量通常只有幾個字節多。

保護字節的目的是在發出delete[]時檢測這些字節的值是否有變化。如果釋放後保護字節發生了變化,那麼系統可以檢測到你做錯了什麼。

很可能,運行時檢測到您覆蓋了保護字節,因此可能會標記出「堆損壞」。但是,當您寫入mymem[32]時,這是在分配的保護字節之外(我高度懷疑係統分配了32個字節作爲保護字節),因此運行時無法檢測到您在分配空間之外寫入的內容。

+0

謝謝..我試着改變memcpy來使用偏移量0f 8,它和2 – singh 2014-09-29 09:58:34

+0

一樣。可能有超過8個字節用作保護字節。它取決於運行時庫。 – PaulMcKenzie 2014-09-29 17:19:22

1

在這兩種情況下,您正在寫分配內存之外,並調用未定義的行爲。一旦出現UB,您可能會得到預期的或意外的結果。