删除2D指针矩阵时发生崩溃[检测到堆损坏]

时间:2015-12-29 10:44:59

标签: c++ matrix visual-studio-2015

我随机创建了两个矩阵A0和A1。之后,我将这两个矩阵复制到A01矩阵,例如

[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

2 个答案:

答案 0 :(得分: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)); // (*)

标记的行为您完成矩阵的所有分配和初始化(除了随机值),您也不必担心以后释放内存。

它仍然不是一个合适的矩阵类,但它需要你承担一些责任。

答案 1 :(得分: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;