2015-12-29 38 views
0

我隨機創建了兩個矩陣A0和A1,它們的大小是隨機的。之後,我將這兩個矩陣複製到A01矩陣,如刪除2D指針矩陣時發生崩潰[檢測到堆損壞]

[A0 | 0 ] 
[0 | A1] 

最後,我刪除了它們的內存。不過,我只運行約3-5倍,在此之後,該方案如

enter image description here

我使用的Visual Studio 2015年什麼是發生在我的代碼檢測錯誤?刪除指針矩陣是錯誤的嗎?

這是我的全碼

#include <iostream> 
#include <stdlib.h> 
#include <time.h>  /* time */ 
#define random(x) (rand()%x) 
typedef unsigned char U8; 
typedef unsigned int U32; 
void create_and_delete_matrix() 
{ 
    U32 M0,M1,M01; 
    U32 m_L0,m_L1,m_L01; 
    U32 range = 20; 
    M0 = random(range) + 1; 
    m_L0 = random(range) + 1; 
    M1 = random(range) + 1; 
    m_L1 = random(range) + 1; 
    M01 = M0 + M1; 
    m_L01 = m_L0 + m_L1; 

    U8** A0 = new U8*[M0]; 
    U8** A1 = new U8*[M1]; 
    U8** A01 = new U8*[M01]; 
    //***********For A0***********// 
    for (U32 i = 0; i < M0; ++i){ 
     A0[i] = new U8[m_L0]; 
     memset(A0[i], 0, m_L0*sizeof(U8)); 
    } 
    //***********For A1***********// 
    for (U32 i = 0; i < M1; ++i) { 
     A1[i] = new U8[m_L1]; 
     memset(A1[i], 0, m_L1*sizeof(U8)); 
    } 
    //***********For A01***********// 
    for (U32 i = 0; i < M01; ++i) { 
     A01[i] = new U8[m_L01]; 
     memset(A01[i], 0, m_L01*sizeof(U8)); 
    } 

    //***********Set random data A0 and A1***********// 
    for (U32 i = 0; i < M0; ++i) { 
     for (U32 j = 0; j < m_L0; ++j) { 
      A0[i][j] = random(2); 
      printf("%d ", A0[i][j]); 
     } 
     printf("\n"); 
    } 
    for (U32 i = 0; i < M1; ++i) { 
     for (U32 j = 0; j < m_L1; ++j) { 
      A1[i][j] = random(2); 
      printf("%d ", A1[i][j]); 
     } 
     printf("\n"); 
    } 
    //***********Copy A0 and A1 to A01 ***********// 
    //***********--------------------- ***********// 
    //***********------[A0 | 0 ]-------***********// 
    //***********------[0 | A1]-------***********// 
    //***********--------------------- ***********// 
    for (U32 i = 0; i < M0; ++i){ 
     //A0 to A01 
     memcpy(A01[i] + m_L0, A0[i], m_L0 * sizeof(U8)); 
    } 
    for (U32 i = 0; i < M1; ++i){ 
     // A1 to A01 
     memcpy(A01[i + M0] + m_L0, A1[i], m_L1 * sizeof(U8)); 
    } 
    //**********Print result of A01**********// 
    for (U32 i = 0; i < M01; ++i) { 
     for (U32 j = 0; j < m_L01; ++j) { 
      printf("%d ", A01[i][j]); 
     } 
     printf("\n"); 
    } 

    //free A0, A1, A01 matrix 
    for (U32 i = 0; i < M0; ++i){ 
     if (i < m_L0){ 
      delete[] A0[i]; 
      A0[i] = NULL; 
     } 
    } 
    delete[] A0; 
    A0 = NULL; 

    for (U32 i = 0; i < M1; ++i) { 
     if (i < m_L1) { 
      delete[] A1[i]; 
      A1[i] = NULL; 
     } 
    } 
    delete[] A1; 
    A1 = NULL; 

    for (U32 i = 0; i < M01; ++i) { 
     if (i < m_L01) { 
      delete[] A01[i]; 
      A01[i] = NULL; 
     } 
    } 
    delete[] A01; 
    A01 = NULL; 

} 
int main(int argc, char **argv) { 
    unsigned int time_ui = static_cast<unsigned int>(time(NULL)); 
    srand(time_ui); 
    for (U32 iter = 0; iter < 100; iter++){ 
     create_and_delete_matrix(); 
    } 
    return 0; 
} 

這是live demo code

我在Ubuntu還測試使用g ++和誤差是

*** Error in `main': free(): invalid next size (fast): 0x0000000001a58600 ***              
======= Backtrace: =========                          
/lib64/libc.so.6(+0x7850e)[0x7ff6e22d750e]                       
/lib64/libc.so.6(cfree+0x5b5)[0x7ff6e22e3165]                      
main[0x40107b]                              
main[0x401105]                              
/lib64/libc.so.6(__libc_start_main+0xf0)[0x7ff6e227efe0]                   
main[0x400939]                              
======= Memory map: ========                          
00400000-00402000 r-xp 00000000 fd:198 59464901       /home/cg/root/main           
00601000-00602000 r--p 00001000 fd:198 59464901       /home/cg/root/main           
00602000-00603000 rw-p 00002000 fd:198 59464901       /home/cg/root/main 
+0

你已經通過調試器中運行你的代碼,對不對?另外,當你使用'new []'和'delete []'時,這或多或少是C99,而不是C++。 – Zeta

+0

是的。我通過Kdevelop運行visual Studio 2015和Ubuntu中的g ++調試 – Jame

+0

抱歉。我會清理它。但它仍然有錯誤 – Jame

回答

2

問題是在這裏

for (U32 i = 0; i < M0; ++i){ 
    //A0 to A01 
    memcpy(A01[i] + m_L0, A0[i], m_L0 * sizeof(U8)); 
} 
for (U32 i = 0; i < M1; ++i){ 
    // A1 to A01 
    memcpy(A01[i + M0] + m_L0, A1[i], m_L1 * sizeof(U8)); 
} 

應該

for (U32 i = 0; i < M0; ++i){ 
    //A0 to A01 
    memcpy(A01[i], A0[i], m_L0 * sizeof(U8)); 
} 
for (U32 i = 0; i < M1; ++i){ 
    // A1 to A01 
    //After m_L0 elements 
    memcpy(A01[i] + m_L0, A1[i], m_L1 * sizeof(U8)); 
} 

或者你也可以複製單元方式,這將使其更具可讀性。

此外,這裏

for (U32 i = 0; i < M0; ++i){ 
    A0[i] = new U8[m_L0]; 
} 
for (U32 i = 0; i < M0; ++i){ 
    A0[i] = new U8[m_L0]; 
    memset(A0[i], 0, m_L0*sizeof(U8)); 
} 
//***********For A1***********// 
for (U32 i = 0; i < M1; ++i){ 
    A1[i] = new U8[m_L1]; 
} 
for (U32 i = 0; i < M1; ++i) { 
    A1[i] = new U8[m_L1]; 
    memset(A1[i], 0, m_L1*sizeof(U8)); 
} 

要創建內存泄漏。第一循環不是必需的。如果可能的話,使用初始化器初始化爲0。

爲了避免這裏的內存管理,您可以使用std::vectorreserve

編輯 免費,必須補充你的配置:

for (U32 i = 0; i < M1; ++i) { 
    delete [] A0[i]; 
} 

delete [] A0; 
+0

是的。這是正確的。我錯了將A0複製到A01。抱歉。我的免費矩陣功能如何? – Jame

+0

自由矩陣看起來不錯,只需從0運行我到所需的限制,而不是如果檢查循環內。 – doptimusprime

+0

你可以告訴我你的代碼,它談論「運行我從0到所需的限制,而不是如果檢查循環內」 – Jame

4

未定義行爲由於重疊在/錯誤範圍memcpy

請注意,您的代碼或多或少是C,而不是C++。你可以讓你的生活變得更加簡單,如果你使用std::vector,例如:

typedef std::vector<U8>   vector_u8_t; 
typedef std::vector<vector_u8_t> matrix_u8_t; 

matrix_u8_t A0(M0, vector_u8_t(m_L0, 0)); // (*) 

標線爲你做矩陣的所有的分配和初始化(除了隨機值),你也不要不得不擔心後來釋放你的記憶。

它仍然不是一個適當的矩陣類,但它需要你的一些責任。