0

I made 2d array(matrix) + alloc and free functions to manage memory but it isnt working well, valgrind prints many errors and information that memory was lost.

Alloc: parametr s means size of matrix

int** alloc(int s)
{
    int** matrix;
    int i;

    matrix = (int**)malloc(s * sizeof(int*));
    for (i = 0; i < s; i++)
    {
        matrix[i] = calloc(s, sizeof(int));
    }

    return matrix;
}

Free

void matrix_free(int*** matrix, int s)
{
    int i;
    for(i = 0; i < s; i++)
    {
        free(*((matrix)+i));
    }
    free(matrix);

}

Valgrind: Many errors like this:

Invalid read of size 8
==3767==    at 0x4FAA8D4: buffer_free (in /lib/x86_64-linux-gnu/libc-2.24.so)
==3767==    by 0x4FAA942: __libc_freeres (in /lib/x86_64-linux-gnu/libc-2.24.so)
==3767==    by 0x4A276EC: _vgnU_freeres (in /usr/lib/valgrind/vgpreload_core-amd64-linux.so)
==3767==    by 0x4E73292: __run_exit_handlers (exit.c:98)
==3767==    by 0x4E73339: exit (exit.c:105)
==3767==    by 0x4E593F7: (below main) (libc-start.c:325)
==3767==  Address 0x52000e8 is 168 bytes inside a block of size 552 free'd
==3767==    at 0x4C2DD6B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3767==    by 0x108BBB: matrix_free (m1.c:68)
==3767==    by 0x108B69: main (m1.c:58)
==3767==  Block was alloc'd at
==3767==    at 0x4C2CB3F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3767==    by 0x4EA7F2C: __fopen_internal (iofopen.c:69)
==3767==    by 0x108919: main (m1.c:16)
==3767== 
==3767== 
==3767== HEAP SUMMARY:
==3767==     in use at exit: 36 bytes in 3 blocks
==3767==   total heap usage: 7 allocs, 6 frees, 5,732 bytes allocated
==3767== 
==3767== LEAK SUMMARY:
==3767==    definitely lost: 36 bytes in 3 blocks
==3767==    indirectly lost: 0 bytes in 0 blocks
==3767==      possibly lost: 0 bytes in 0 blocks
==3767==    still reachable: 0 bytes in 0 blocks
==3767==         suppressed: 0 bytes in 0 blocks
  • 2
    Please provide a [mcve] including the calls to these functions that can reproduce the problem. – kaylum Nov 07 '16 at 19:56
  • 1
    For starters `int*** matrix` looks suspicious. The matrix is allocated as an `int **` but somehow the free is releasing an `int ***`. So please provide an MCVE so we can see the code in context and we can then give a definitive answer. – kaylum Nov 07 '16 at 19:58
  • `matrix_free` doesn't look right. You're passing in an `int***` so the `free`s in your `for` loop should have `**` dereference and the final `free` should be `free(*matrix);` – yano Nov 07 '16 at 19:59
  • Why is the original representation based on `int **` pointer, but `free` suddenly expects `int ***` pointer? Where did the extra `*` come from? Why do you cast the result of `malloc` (and yet don't cast the result of `calloc`)? – AnT stands with Russia Nov 07 '16 at 19:59
  • 1
    this question has been asked a lot of times, among which one person even asked a 5d version. we really need to write this into the SO documentation. – user3528438 Nov 07 '16 at 20:08
  • If you think that any answer has solved your problem, please consider accepting it (the green checkmark to the left of the answer). This will indicate to the community that the question has been answered and will give some reputation to you and the answerer. – 2501 Nov 16 '16 at 10:43

1 Answers1

1

The free function in this case doesn't take a pointer that points to the allocated memory, but a pointer to that pointer.

To free the memory you need to first obtain that pointer.

void matrix_free(int*** matrix, int s)
{
    int** m = *matrix;
    int i;
    for(i = 0; i < s; i++)
    {
        free( m[i] );
    }
    free( m );

    *matrix = NULL;
}

This variant also enables you to set the argument to NULL:

matrix_free( &matrix , s );
assert( matrix == NULL );
2501
  • 25,460
  • 4
  • 47
  • 87