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
}
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.