common: add autofree helper

Much like the auto-closing helper for file descriptors, add a new
auto-free helper that is meant to be used with dynamically allocated
memory, a la:
  autofree char *data = NULL;
  ...
  data = malloc(size);
When data goes out of scope, cleanup_free will be called with &data,
i.e. cleanup_free(&data), which in turn will call free(3) data. In
order to work with all types, e.g. 'char *' (resulting in char **
being passed to cleanup_free) or 'int *' (resulting in int ** being
passed to cleanup_free), cleanup_free is defined to work with void *,
hence the odd-looking cast: void *target = *(void **) ptr.
This commit is contained in:
Christian Kellner 2019-10-04 15:54:33 +02:00
parent 35fb7f5baf
commit 4b59818fd4
2 changed files with 22 additions and 0 deletions

View File

@ -39,3 +39,4 @@ POSSIBILITY OF SUCH DAMAGE.
* a specific call to the function the linker will expect an definition. * a specific call to the function the linker will expect an definition.
*/ */
extern inline void cleanup_close(int *fd); extern inline void cleanup_close(int *fd);
extern inline void cleanup_free(void *ptr);

View File

@ -31,6 +31,7 @@ POSSIBILITY OF SUCH DAMAGE.
#pragma once #pragma once
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/param.h> #include <sys/param.h>
#include <unistd.h> #include <unistd.h>
@ -80,3 +81,23 @@ inline void cleanup_close(int *fd_ptr)
* like "autoclose_fd int fd = -1;". * like "autoclose_fd int fd = -1;".
*/ */
#define autoclose_fd __attribute__((cleanup(cleanup_close))) #define autoclose_fd __attribute__((cleanup(cleanup_close)))
/**
* Helper function for auto-freeing dynamically allocated memory. Does nothing
* if *ptr is NULL (ptr must not be NULL).
*/
inline void cleanup_free(void *ptr)
{
/* The function is defined to work with 'void *' because
* that will make sure it compiles without warning also
* for all types; what we are getting passed into is a
* pointer to a pointer though, so we need to cast */
void *target = *(void **)ptr;
free(target); /* free can deal with NULL */
}
/**
* Helper macro for auto-freeing dynamically allocated memory: use by
* prefixing the variable, like "autofree char *data = NULL;".
*/
#define autofree __attribute__((cleanup(cleanup_free)))