Add g_autofree

The g_autoptr() being associated with the type name works out really
well for things like GHashTable.  However, it's a bit more awkward to
associate with "gchar".  Also because one can't use "char".
Similarly, there are a lot of other "bare primitive array" types that
one might reasonably use.

This patch does not remove the autoptr for "gchar", even though I
think it's rather awkward and strange.

Also while we're here, add a test case for the cleanup bits.

https://bugzilla.gnome.org/show_bug.cgi?id=744747
This commit is contained in:
Colin Walters 2015-02-15 08:58:44 -05:00
parent 2844f239f6
commit d0105f1c08
5 changed files with 86 additions and 0 deletions

View File

@ -2422,6 +2422,40 @@
* Since: 2.44 * 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: * G_DEFINE_AUTOPTR_CLEANUP_FUNC:
* @TypeName: a type name to define a g_autoptr() cleanup function for * @TypeName: a type name to define a g_autoptr() cleanup function for

View File

@ -21,6 +21,14 @@
#error "Only <glib.h> can be included directly." #error "Only <glib.h> can be included directly."
#endif #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(GAsyncQueue, g_async_queue_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GBookmarkFile, g_bookmark_file_free) G_DEFINE_AUTOPTR_CLEANUP_FUNC(GBookmarkFile, g_bookmark_file_free)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GBytes, g_bytes_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC(GBytes, g_bytes_unref)

View File

@ -402,6 +402,7 @@
G_GNUC_END_IGNORE_DEPRECATIONS G_GNUC_END_IGNORE_DEPRECATIONS
#define g_autoptr(TypeName) _GLIB_CLEANUP(_GLIB_AUTOPTR_FUNC_NAME(TypeName)) _GLIB_AUTOPTR_TYPENAME(TypeName) #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_auto(TypeName) _GLIB_CLEANUP(_GLIB_AUTO_FUNC_NAME(TypeName)) TypeName
#define g_autofree _GLIB_CLEANUP(g_autoptr_cleanup_generic_gfree)
#else /* not GNU C */ #else /* not GNU C */
/* this (dummy) macro is private */ /* this (dummy) macro is private */

View File

@ -200,6 +200,12 @@ check-am: gtester-xmllint-check
private_LDFLAGS = @G_THREAD_LIBS@ private_LDFLAGS = @G_THREAD_LIBS@
endif endif
if HAVE_GCC
test_programs += \
autoptr \
$(NULL)
endif
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
if HAVE_EVENTFD if HAVE_EVENTFD

37
glib/tests/autoptr.c Normal file
View File

@ -0,0 +1,37 @@
#include <glib.h>
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 ();
}