shared: avoid invoking g_free() with NULL from gs_free cleanup attribute

In general, it's fine to pass %NULL to g_free().

However, consider:

    char *
    foo (void)
    {
        gs_free char *value = NULL;

        value = g_strdup ("hi");
        return g_steal_pointer (&value);
    }

gs_free, gs_local_free(), and g_steal_pointer() are all inlinable.
Here the compiler can easily recognize that we always pass %NULL to
g_free(). But with the previous implementation, the compiler would
not omit the call to g_free().

Similar patterns happen all over the place:

    gboolean
    baz (void)
    {
        gs_free char *value = NULL;

        if (!some_check ())
            return FALSE;

        value = get_value ();
        if (!value)
            return FALSE;

        return TRUE;
    }

in this example, g_free() is only required after setting @value to
non-NULL.

Note that this does increase the binary side a bit (4k for libnm, 8k
for NetworkManager, with "-O2").
This commit is contained in:
Thomas Haller 2018-09-27 14:20:02 +02:00
parent ba491a6674
commit d060b7b379
2 changed files with 6 additions and 6 deletions

View file

@ -99,7 +99,7 @@ static inline void name (Type *v) \
* Call g_free() on a variable location when it goes out of scope.
*/
#define gs_free nm_auto(gs_local_free)
NM_AUTO_DEFINE_FCN_VOID (void *, gs_local_free, g_free)
NM_AUTO_DEFINE_FCN_VOID0 (void *, gs_local_free, g_free)
/**
* gs_unref_object:
@ -160,7 +160,7 @@ NM_AUTO_DEFINE_FCN0 (GHashTable *, gs_local_hashtable_unref, g_hash_table_unref)
* of scope.
*/
#define gs_free_slist nm_auto(gs_local_free_slist)
NM_AUTO_DEFINE_FCN (GSList *, gs_local_free_slist, g_slist_free)
NM_AUTO_DEFINE_FCN0 (GSList *, gs_local_free_slist, g_slist_free)
/**
* gs_unref_bytes:
@ -178,7 +178,7 @@ NM_AUTO_DEFINE_FCN0 (GBytes *, gs_local_bytes_unref, g_bytes_unref)
* Call g_strfreev() on a variable location when it goes out of scope.
*/
#define gs_strfreev nm_auto(gs_local_strfreev)
NM_AUTO_DEFINE_FCN (char **, gs_local_strfreev, g_strfreev)
NM_AUTO_DEFINE_FCN0 (char **, gs_local_strfreev, g_strfreev)
/**
* gs_free_error:
@ -222,7 +222,7 @@ static inline int nm_close (int fd);
* However, let's never mix them. To free malloc'ed memory, always use
* free() or nm_auto_free.
*/
NM_AUTO_DEFINE_FCN_VOID (void *, _nm_auto_free_impl, free)
NM_AUTO_DEFINE_FCN_VOID0 (void *, _nm_auto_free_impl, free)
#define nm_auto_free nm_auto(_nm_auto_free_impl)
NM_AUTO_DEFINE_FCN0 (GVariantIter *, _nm_auto_free_variant_iter, g_variant_iter_free)
@ -231,7 +231,7 @@ NM_AUTO_DEFINE_FCN0 (GVariantIter *, _nm_auto_free_variant_iter, g_variant_iter_
NM_AUTO_DEFINE_FCN0 (GVariantBuilder *, _nm_auto_unref_variant_builder, g_variant_builder_unref)
#define nm_auto_unref_variant_builder nm_auto(_nm_auto_unref_variant_builder)
NM_AUTO_DEFINE_FCN (GList *, _nm_auto_free_list, g_list_free)
NM_AUTO_DEFINE_FCN0 (GList *, _nm_auto_free_list, g_list_free)
#define nm_auto_free_list nm_auto(_nm_auto_free_list)
NM_AUTO_DEFINE_FCN0 (GChecksum *, _nm_auto_checksum_free, g_checksum_free)

View file

@ -43,7 +43,7 @@ nm_free_secret (char *secret)
}
}
NM_AUTO_DEFINE_FCN (char *, _nm_auto_free_secret, nm_free_secret)
NM_AUTO_DEFINE_FCN0 (char *, _nm_auto_free_secret, nm_free_secret)
/**
* nm_auto_free_secret:
*