diff --git a/glib/docs.c b/glib/docs.c index f7a0bf240..9169d85ea 100644 --- a/glib/docs.c +++ b/glib/docs.c @@ -2422,6 +2422,40 @@ * Since: 2.44 */ +/** + * g_autofree: + * + * Macro to add an attribute to pointer variable to ensure automatic + * cleanup using g_free(). + * + * This macro differs from g_autoptr() in that it is an attribute supplied + * before the type name, rather than wrapping the type definition. Instead + * of using a type-specific lookup, this macro always calls g_free() directly. + * + * This means it's useful for any type that is returned from + * g_malloc(). + * + * Otherwise, this macro has similar constraints as g_autoptr() - only + * supported on GCC and clang, the variable must be initialized, etc. + * + * |[ + * gboolean + * operate_on_malloc_buf (void) + * { + * g_autofree guint8* membuf = NULL; + * + * membuf = g_malloc (8192); + * + * /* Some computation on membuf */ + * + * /* membuf will be automatically freed here */ + * return TRUE; + * } + * ]| + * + * Since: 2.44 + */ + /** * G_DEFINE_AUTOPTR_CLEANUP_FUNC: * @TypeName: a type name to define a g_autoptr() cleanup function for diff --git a/glib/glib-autocleanups.h b/glib/glib-autocleanups.h index 902e95275..80d7b2bd4 100644 --- a/glib/glib-autocleanups.h +++ b/glib/glib-autocleanups.h @@ -21,6 +21,14 @@ #error "Only can be included directly." #endif +static inline void +g_autoptr_cleanup_generic_gfree (void *p) +{ + void **pp = (void**)p; + if (*pp) + g_free (*pp); +} + G_DEFINE_AUTOPTR_CLEANUP_FUNC(GAsyncQueue, g_async_queue_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC(GBookmarkFile, g_bookmark_file_free) G_DEFINE_AUTOPTR_CLEANUP_FUNC(GBytes, g_bytes_unref) diff --git a/glib/gmacros.h b/glib/gmacros.h index 62b61cb09..b34cc771f 100644 --- a/glib/gmacros.h +++ b/glib/gmacros.h @@ -402,6 +402,7 @@ G_GNUC_END_IGNORE_DEPRECATIONS #define g_autoptr(TypeName) _GLIB_CLEANUP(_GLIB_AUTOPTR_FUNC_NAME(TypeName)) _GLIB_AUTOPTR_TYPENAME(TypeName) #define g_auto(TypeName) _GLIB_CLEANUP(_GLIB_AUTO_FUNC_NAME(TypeName)) TypeName +#define g_autofree _GLIB_CLEANUP(g_autoptr_cleanup_generic_gfree) #else /* not GNU C */ /* this (dummy) macro is private */ diff --git a/glib/tests/Makefile.am b/glib/tests/Makefile.am index 445040ade..bdcd0cbf5 100644 --- a/glib/tests/Makefile.am +++ b/glib/tests/Makefile.am @@ -200,6 +200,12 @@ check-am: gtester-xmllint-check private_LDFLAGS = @G_THREAD_LIBS@ endif +if HAVE_GCC +test_programs += \ + autoptr \ + $(NULL) +endif + # ----------------------------------------------------------------------------- if HAVE_EVENTFD diff --git a/glib/tests/autoptr.c b/glib/tests/autoptr.c new file mode 100644 index 000000000..b2db3354a --- /dev/null +++ b/glib/tests/autoptr.c @@ -0,0 +1,37 @@ +#include + +static void +test_autofree (void) +{ + g_autofree char *p = NULL; + g_autofree char *p2 = NULL; + g_autofree char *alwaysnull = NULL; + + p = g_malloc (10); + p2 = g_malloc (42); + + if (TRUE) + { + g_autofree guint8 *buf = g_malloc (128); + g_autofree char *alwaysnull_again = NULL; + + buf[0] = 1; + } + + if (TRUE) + { + g_autofree guint8 *buf2 = g_malloc (256); + + buf2[255] = 42; + } +} + +int +main (int argc, char *argv[]) +{ + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/autoptr/autofree", test_autofree); + + return g_test_run (); +}