g_array_free, g_ptr_array_free: decrement refcount if not the last ref
authorSimon McVittie <simon.mcvittie@collabora.co.uk>
Wed, 14 Dec 2011 16:56:15 +0000 (16:56 +0000)
committerSimon McVittie <simon.mcvittie@collabora.co.uk>
Wed, 14 Dec 2011 18:10:31 +0000 (18:10 +0000)
foo_free is conceptually "worth" one unref; not decrementing the
refcount here means the GArray or GPtrArray wrapper (but not its
contents) would leak in the following call sequence:

    p = g_ptr_array_new ();
    g_ptr_array_ref (p);
    g_ptr_array_free (p, TRUE);
    g_ptr_array_unref (p);

Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=666113
Reviewed-by: Emmanuele Bassi <ebassi@linux.intel.com>
glib/garray.c

index 718409d..14aef84 100644 (file)
@@ -305,7 +305,7 @@ g_array_free (GArray   *farray,
   flags = (free_segment ? FREE_SEGMENT : 0);
 
   /* if others are holding a reference, preserve the wrapper but do free/return the data */
-  if (g_atomic_int_get (&array->ref_count) > 1)
+  if (!g_atomic_int_dec_and_test (&array->ref_count))
     flags |= PRESERVE_WRAPPER;
 
   return array_free (array, flags);
@@ -982,7 +982,7 @@ g_ptr_array_free (GPtrArray *farray,
   flags = (free_segment ? FREE_SEGMENT : 0);
 
   /* if others are holding a reference, preserve the wrapper but do free/return the data */
-  if (g_atomic_int_get (&array->ref_count) > 1)
+  if (!g_atomic_int_dec_and_test (&array->ref_count))
     flags |= PRESERVE_WRAPPER;
 
   return ptr_array_free (farray, flags);