0

I am writing a program that extracts a submatrix block (half of source) from a bigger matrix.

The idea is to loop on rows, and copy each row from source matrix with memcpy.

Only problem is when I do a free() on the initial source matrix I get munmap_chunk() error. I know this happens when I free a pointer that was not allocated by malloc. But this makes no sense here! my mat[i] that I try to free was allocated by malloc. And it was only used as source in memcpy. Is memcpy modifying the source?!

My code looks like this:

void print(int ** data, size_t m,size_t n)
{

    int i,j;
    
    printf("\n");
    for(i=0;i<m;i++)
    {    for(j=0;j<n;j++)
        {
            printf("%d ",data[i][j]);
        }
    printf("\n");
    }
}


void init(int** tab, int n,int m ){
    const int size_s = 8;
    int mat[size_s][size_s] = {
        { 1, 2, 3, 4, 5, 6, 7, 8},
        { 9,10,11,12,13,14,15,16},
        {17,18,19,20,21,22,23,24},
        {25,26,27,28,29,30,31,32},
        {33,34,35,36,37,38,39,40},
        {41,42,43,44,45,46,47,48},
        {49,50,51,52,53,54,55,56},
        {57,58,59,60,61,62,63,64}
    };

    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            tab[i][j]= mat[i][j];
        }
    }
}

--Main function

int main (void){
    const int n = 8;
    int sub_mtrx_size = n/2;
    int ** mat =  malloc(sizeof(int*) * n);
    int ** submat =  malloc(sizeof(int*) * n/2);
    for (int k = 0; k < n; k++) {
        mat[k] =  malloc(sizeof(int) * n);
        if ( k < n/2){
            submat[k] =  malloc(sizeof(int) * (n/2));
        }
        
    }
    init (mat,n,n);
    // start problem: when doing memcpy this issue happen, commenting this leads to no errors
    memcpy( submat[0] , mat[0], sub_mtrx_size* sizeof(&submat) );
    memcpy( submat[1] , mat[1], sub_mtrx_size* sizeof(&submat) );
    memcpy( submat[2] , mat[2], sub_mtrx_size* sizeof(&submat) );
    memcpy( submat[3] , mat[3], sub_mtrx_size* sizeof(&submat) );
    // end problem 
    
    print(submat,4,4);

      for (int i = 0; i < n; i++)
    {
        // free(mat[i]); // this line creates the problem !
        if ( i < n/2){
            free(submat[i]);
        }
    }
    free (mat);
    free (submat);
    return 0;
}

How do I avoid this issue and free the memory properly?

Thanks

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
user206904
  • 504
  • 4
  • 16
  • 3
    `sizeof(&submat)` ==> `sizeof **submat` or `sizeof(int)`. You copy too much data to the buffers, so overwritting something important. – mch Feb 09 '22 at 12:32
  • @Jabberwock, I added both. just to be clear, I am reporting the next person who tells me "your code contains useless details" – user206904 Feb 09 '22 at 12:32
  • @mch thanks for your comment. is that supposed to solve the problem? or was it just a general comment? Your remark is true. But I don't understand the difference, aren't all of them interchangeable (in this example)? – user206904 Feb 09 '22 at 12:34
  • 1
    `int mat[size_s][size_s] = {...` does not even compile: https://godbolt.org/z/W3qnGqv6P – mch Feb 09 '22 at 12:35
  • I don't know if it is the only problem. `sizeof(&submat)` is `sizeof(int***)`, the size of a pointer, usually 8 on modern systems. `sizeof(int)` is usually 4. – mch Feb 09 '22 at 12:36
  • Idk for The `size_s ` error you have. It compiles fine for me and I see nothing wrong in this part of the code. However the hint you indicated seems to solve the problem! I will double-check. – user206904 Feb 09 '22 at 12:37
  • 1
    But looks fine after that: https://godbolt.org/z/acKasr7ao – mch Feb 09 '22 at 12:39
  • @mch Edit: OK, I can confirm your hint solves it!! But how come? aren't both `sizeof(**submat)` and `sizeof(&submat)` giving the same thing and simply we care about the int here? and both are read only operations, then why does the problem happen with the free? could you please write an answer if you know why? :) I will mark it – user206904 Feb 09 '22 at 12:41
  • 1
    "aren't both sizeof(**submat) and sizeof(&submat) giving the same thing" Absolutely positively not. Why would they be the same? What gives you this idea? – n. m. could be an AI Feb 09 '22 at 12:48
  • @n.1.8e9-where's-my-sharem. ok you are right. I printed it! Thanks – user206904 Feb 09 '22 at 12:50
  • 1
    The root of all your problems are the inefficient and fragmented pointer tables. You should replace those with 2D arrays instead and then you can quickly copy the whole array in one go. See [Correctly allocating multi-dimensional arrays](https://stackoverflow.com/questions/42094465/correctly-allocating-multi-dimensional-arrays). Similarly your functions should be modified to accept a 2D array instead of a pointer-to-pointer. – Lundin Feb 09 '22 at 13:15

1 Answers1

1

Calls of memcpy like this

memcpy( submat[0] , mat[0], sub_mtrx_size* sizeof(&submat) );

is incorrect. The expression sizeof(&submat) gives the size of a pointer of the type int ***.

You need to write

memcpy( submat[0] , mat[0], sub_mtrx_size* sizeof( int) );

or

memcpy( submat[0] , mat[0], sub_mtrx_size * sizeof( *submat[0] ) );
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335