Yesterday I was discussing a bug in some code using a GHashTable with Will and we both started to wonder if there is any reason to use g_hash_table_insert instead of g_hash_table_replace.
First of all an example, look at this code and try to find the bug.
#include <glib.h>
static void
add_entry (GHashTable *ht, const gchar *config)
{
gchar **split_config = g_strsplit (config, "=", 2);
if (g_strv_length (split_config) == 2) {
gchar *key = g_utf8_strdown (split_config[0], -1);
gchar *value = g_strdup (split_config[1]);
g_hash_table_insert (ht, key, value);
g_print ("Set %s to %sn", key, value);
}
g_strfreev (split_config);
}
int
main (int argc, char **argv)
{
GHashTable *ht = g_hash_table_new_full (g_str_hash,
g_str_equal, g_free, g_free);
gint i;
for (i = 1; i < argc; i++)
add_entry (ht, argv[i]);
g_hash_table_unref (ht);
return 0;
}
If it’s not clear where the bug is, try invoking the program with “apples=42 Pears=12 APPLES=10” on the command line.
If a key already exists in the hash table, the key passed to g_hash_table_insert is destroyed and you cannot use it afterwards. This behaviour is documented, but it’s easy to find code affected by this bug. g_hash_table_replace behaves like g_hash_table_insert, but without this problem.
Is there any good reason for using g_hash_table_insert instead of g_hash_table_replace? Can you come up with a non-contrived example where you want the behaviour of the former?