Faced problem to add a new row to a matrix in C. corrupted size vs. prev_size

83 Views Asked by At

I am trying to develop a linear algebra library from scratch for various matrix operations. I faced a problem while adding a new row to a matrix. I store the matrix using the Column major formula, and using realloc I add a new row to the end position. To be precise, we have a m x n matrix, and after adding a new row to the end, we will get a matrix of size (m+1) xn. But I am getting an error "corrupted size vs. prev_size". It would be great if anyone could help me to figure out the issue. Please find piece of the code below. Thanks.

// Generate a random matrix of size row x col
void generate_rand_matrix(double *a, int row, int col){
    for(int i=0; i<row; ++i){
        for(int j=0; j<col; ++j){
            a[i + row*j] = (double)rand() / (double)RAND_MAX;
        }
    }
}

// Generate a random vector of size row
void generate_rand_vector(double *a, int row){
    int max = 1, min = -1;
    for(int i=0; i<row; ++i){
        a[i] = (double)rand() / (double)RAND_MAX;
    }
}



// Add a new row of size n, "v" to the end of matrix "mat". New size of the matrix becomes (m+1) x n. "v" must be of size n. 
void add_row(double *mat, int m, int n, double *v){
    mat = (double*)realloc(mat, (m+1) * n * sizeof(double));
    for(int j=0; j<n; ++j){
        mat[m + (m+1)*j] = v[j];
    }
}

// Print a matrix of size row x col
void print_matrix(double *a, int row, int col){
    for(int i=0; i<row; ++i){
        for(int j=0; j<col; ++j){
            printf("%lf\t", a[i + row*j]);
        }
        printf("\n");
    }
}

int main(){
   int N = 16;
   double *rand_mat = (double*) malloc(N*N*sizeof(double));
   generate_rand_matrix(rand_mat, N, N);
   
   // row
   double *new_row = (double*) malloc(N*sizeof(double));
   generate_rand_vector(new_row, N);
   add_row(rand_mat, N+1, N, new_row); // PROBLEM 

}

It would be great if anyone could help me to figure out the issue. Please find the piece of the code below. Thanks.

1

There are 1 best solutions below

0
Ted Lyngmo On

You don't save the pointer after realloc since mat is local to the add_row function. This means that rand_mat in main still points at the old memory location in case realloc actually reallocated the memory allocation.

You need to either send in a pointer to your pointer:

bool add_row(double **mat, int m, int n, double *v) {
//                  ^^
    double *np = realloc(*mat, m * n * sizeof(double));
    if (np == NULL) return false;
    for (int j = 0; j < n; ++j) {
        np[(m - 1) * n + j] = v[j]; // m-1 is the new row
    }
    *mat = np; // save the new pointer
    return true;
}

and call it like this:

add_row(&rand_mat, N + 1, N, new_row);
//      ^

... or return the new pointer after reallocation.

Also note that since you already send in N + 1 to the function you shouldn't allocate m + 1 rows, only m and that you've multiplied with j instead of m which I've ocrrected above.


It may be simpler to keep the matrix information in a struct:

typedef struct {
    double *data;
    size_t cols;
    size_t rows;
} matrix;

A function to add a row would then only need to take a matrix* and a pointer to the row data to add:

bool matrix_add_row(matrix *mat, const double *v) {
    const size_t rowsize = mat->cols * sizeof *mat->data;

    double *np = realloc(mat->data, (mat->rows + 1) * rowsize);
    if (np == NULL) return false;

    memcpy(np + mat->rows * mat->cols, v, rowsize);

    mat->data = np;
    mat->rows++;
    return true;
}

Demo