Search code examples
carraysattributesmallocfree

Generic function to free 2d arrays with cleanup attribute in C


I've recently discovered __attribute__((cleanup)) which is very handy. I have made a generic function to free any type of pointer and it works fine.

#define _autofree_ __attribute__ ((cleanup(free_pointer)))

...

void free_pointer(void *pointer)
{
    free(*(void **) pointer);
}

But it's not as easy when it comes to freeing 2d arrays. As far as I know cleanup uses a pointer to the given pointer for stack restriction reasons, and it's a good thing because it doesn't use a copy of it at any point. Anyway, Dereferencing a (void **) cast to pass through "derefencing void *" errors works but then if I do

#define _autofree2d_ __attribute__ ((cleanup(free_pointer_array)))

...

void free_pointer_array(void *pointer_array)
{
    for (size_t i = 0 ; (void **) pointer_array[i] ; ++i)
        free(*(void **) pointer_array[i]);
    free(*(void ***) pointer_array);
}

I end up dereferencing a void * because of the bracketed [i]. Also this just doesn't look right.

I'm also trying doing it in a less generic way using char pointers (as I'm currently working with a word array) and it compiles but gives we a segfault because of an invalid free.

void free_pointer_array(char ***array)
{
    for (size_t i = 0 ; *array[i] ; ++i)
        free(*array[i]);
    free(**array);              // Tried using ***array and got
                                // "pointer from integer without a cast" error
}

Solution

  • As mentioned by Andrew Henle in the comments, my method of allocation was the problem. I was making a look-up table rather than an actual 2d array. Using the method described here : Correctly allocating multi-dimensional arrays, I can simply use my original _autofree_ macro for arrays of any dimension.