0

I am now using some c++ code to compute matrix inverse and the matrix is stored in a two-dimensional array.

However, I met some possible memory issues that I had no idea how to fix it. Sometimes, I can get good return while sometimes error occurs. Really appreciate if you can give advice.

I got error message "malloc: *** error for object 0x163faaa38: incorrect checksum for freed object - object was probably modified after being freed. ".

Also, please see this picture and I use it to indicate which part of the code might go wrong.

possible error code line

Thank you very much.

long double Determinant(long double **a, int n)
{
    int i, j, j1, j2 ;                    // general loop and matrix subscripts
    long double det = 0 ;                   // init determinant
    // pointer to pointers to implement 2d
    // square array
    long double **m;
    if (n == 1) {                 // should not get here
        det = a[0][0] ;
    }

    else if (n == 2)  {                // basic 2X2 sub-matrix determinate
        // definition. When n==2, this ends the
        det = a[0][0] * a[1][1] - a[1][0] * a[0][1] ;// the recursion series
    }

    // recursion continues, solve next sub-matrix
    else {                             // solve the next minor by building a
        // sub matrix
        det = 0 ;                      // initialize determinant of sub-matrix

        // for each column in sub-matrix
        for (j1 = 0 ; j1 < n ; j1++) {
            // get space for the pointer list
            m = new long double*[n-1];
            //m = (double **) malloc((n-1)* sizeof(double *)) ;

            for (i = 0 ; i < n-1 ; i++)
                m[i] = new long double[n-1];
            //     i[0][1][2][3]  first malloc
            //  m -> +  +  +  +   space for 4 pointers
            //       |  |  |  |          j  second malloc
            //       |  |  |  +-> _ _ _ [0] pointers to
            //       |  |  +----> _ _ _ [1] and memory for
            //       |  +-------> _ a _ [2] 4 doubles
            //       +----------> _ _ _ [3]
            //
            //                   a[1][2]
            // build sub-matrix with minor elements excluded
            for (i = 1 ; i < n ; i++) {
                j2 = 0 ;               // start at first sum-matrix column position
                // loop to copy source matrix less one column
                for (j = 0 ; j < n ; j++) {
                    if (j == j1) continue ; // don't copy the minor column element

                    m[i-1][j2] = a[i][j] ;  // copy source element into new sub-matrix
                    // i-1 because new sub-matrix is one row
                    // (and column) smaller with excluded minors
                    j2++ ;                  // move to next sub-matrix column position
                }
            }

            det += pow(-1.0, 1.0 + j1 + 1.0) * a[0][j1] * Determinant(m, n-1);
            // sum x raised to y power
            // recursively get determinant of next
            // sub-matrix which is now one
            // row & column smaller
            for (i = 0 ; i < n-1 ; i++) delete m[i];// free the storage allocated to
            // to this minor's set of pointers
            // free the storage for the original
            // pointer to pointer
            delete [] m;
        }

    }

    return(det);
}

// calculate the cofactor of element (row,col)
void GetMinor(long double **src, long double **dest, int row, int col, int order)
{
    // indicate which col and row is being copied to dest
    int colCount=0,rowCount=0;

    for(int i = 0; i < order; i++ )
    {
        if( i != row )
        {
            colCount = 0;
            for(int j = 0; j < order; j++ )
            {
                // when j is not the element
                if( j != col )
                {
                    dest[rowCount][colCount] = src[i][j];
                    colCount++;
                }
            }
            rowCount++;
        }
    }
}

// Calculate the determinant recursively.
long double CalcDeterminant(long double **mat, int order)
{
    // order must be >= 0
    // stop the recursion when matrix is a single element
    if( order == 1 )
        return mat[0][0];

    // the determinant value
    long double det = 0;

    // allocate the cofactor matrix
    long double **minor;
    minor = new long double*[order-1];
    for(int i=0;i<order-1;i++)
        minor[i] = new long double[order-1];

    for(int i = 0; i < order; i++)
    {
        // get minor of element (0,i)
        GetMinor(mat, minor, 0, i, order);
        // the recusion is here!

        det += (i%2==1?-1.0:1.0) * mat[0][i] * CalcDeterminant(minor,order-1);
        //det += pow( -1.0, i ) * mat[0][i] * CalcDeterminant( minor,order-1 );
    }

    // release memory
    for(int i=0;i<order-1;i++)
        delete [] minor[i];
    delete [] minor;

    return det;
}


// matrix inversioon

void MatrixInversion(long double **InputM, int order, long double **InvM)
{
    // get the determinant of a
    long double det = 1.0/CalcDeterminant(InputM, order);

    // memory allocation
    long double *temp = new long double[(order-1)*(order-1)];
    long double **minor = new long double*[order-1];
    for(int i=0;i<order-1;i++)
        minor[i] = temp+(i*(order-1));

    for(int j=0;j<order;j++)
    {
        for(int i=0;i<order;i++)
        {
            // get the co-factor (matrix) of A(j,i)
            GetMinor(InputM,minor,j,i,order);
            InvM[i][j] = det*CalcDeterminant(minor,order-1);
            if((i+j)%2 == 1)
                InvM[i][j] = -InvM[i][j];
        }
    }

    // release memory
    //delete [] minor[0];
    delete [] temp;
    for(int i=0; i<order-1; i++)
        delete [] minor[i];
    delete [] minor;
}
Barmar
  • 741,623
  • 53
  • 500
  • 612
ZZ32
  • 21
  • 4

1 Answers1

2

The error is because of this code in the MatrixInversion function;

delete [] temp;
for(int i=0; i<order-1; i++)
    delete [] minor[i];
delete [] minor;

The variables temp and minor were defined as follows:

long double *temp = new long double[(order-1)*(order-1)];
long double **minor = new long double*[order-1];
for(int i=0;i<order-1;i++)
     minor[i] = temp+(i*(order-1));

Each row in the minor matrix does not have new memory allocated to it; rather, it's just a pointer into the temp array. So what happens is you try to delete memory that wasn't allocated with new.

You should remove the for loop deleting the elements of minor. That memory will be freed when you delete [] temp;.

Daniel
  • 6,595
  • 9
  • 38
  • 70
  • Hi, thanks for your reply. I changed that part but still had the same issue. – ZZ32 Apr 18 '18 at 19:29
  • @ZZ32 one thing I recommend is setting pointers to `nullptr` after they've been `delete`d. That way you'll get a segfault immediately when you try to use it. That usually makes debugging easier. – Daniel Apr 18 '18 at 23:41