Browse Source

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.
Christian Kellner 5 years ago
parent
commit
4b59818fd4
2 changed files with 22 additions and 0 deletions
  1. 1 0
      common/common-helpers.c
  2. 21 0
      common/common-helpers.h

+ 1 - 0
common/common-helpers.c

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

+ 21 - 0
common/common-helpers.h

@@ -31,6 +31,7 @@ POSSIBILITY OF SUCH DAMAGE.
 
 #pragma once
 
+#include <stdlib.h>
 #include <string.h>
 #include <sys/param.h>
 #include <unistd.h>
@@ -80,3 +81,23 @@ inline void cleanup_close(int *fd_ptr)
  * like "autoclose_fd int fd = -1;".
  */
 #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)))