On Tue, Mar 14, 2006 at 11:48:56AM +0200, Adrian Vasile wrote:
> I'm having trouble understanding the GHashTable and it's member
> functions.

GHashTable just stores some untyped pointers.

Since it has no idea what type the stored data are, it
cannot make a copies of them and does not make copies of
them.  So...

> I've made the following simple code for testing purposes:
> 
> #include <stdio.h>
> #include <glib.h>
> 
> typedef struct _client
> {
>       guint           id;
>       guint           win;
>       gchar           *name;
>       gchar           *number;
>       gboolean        mute;
> } client ;
> 
> static void print_hash_kv (gpointer key, gpointer value, gpointer
> user_data)
> {
>       gchar   *i = (gchar *) key;
>       client  *d = (client *) value;
>       
>       printf ("<-- %s -> %d , %s, %s in %d.\n", i, d->id, d->name, d->number,
> d->win);
> }
> 
> int main (int argc, char **argv)
> {
>       client          *c, *d;
>       GHashTable      *hash = g_hash_table_new (g_str_hash, g_str_equal); 
> 
>       if ((c = g_new (client, 1)) == NULL)

This cannot happen.  g_new() aborts program when it fails to
allocate the memory.

>       {
>               printf ("unable to alloc c");
>               return 1;
>       }
>               
>       c->id = 2;
>       c->win = 3;
>       c->name = g_strdup ("client1");
>       c->number = g_strdup ("0123456789");
>       c->mute = TRUE;
>       
>       printf ("--> %d , %s, %s in %d.\n", c->id, c->name, c->number, c->win);
>       
>       g_hash_table_insert (hash, g_strdup ("2"), c);

I wonder who is going to free the key.  Perhaps you intended
to use g_hash_table_new_full() and supply a key destroy
function?  Or just get rid of the g_strdup() if keys are
constant strings.

>       g_free (c);

Now the table contains a pointer to freed memory at key "2".
The c you freed here is the same chunk of memory as is
stored in the table.  Remember, no copies, it just stores
some pointer.

>       hash = g_hash_table_ref (hash);

I wonder what is this intended to mean.  You already own
a reference to the hash table -- the initial one.  And
I cannot see any g_hash_table_unref() here, so you will have
two *two* reference to the hash table to the end of program.
Why?

>       if ((d = g_new (client, 1)) == NULL)
>       {
>               printf ("unable to alloc d");
>               return 1;
>       }
> 
>       d->id = 1;
>       d->win = 2;
>       d->name = g_strdup ("client2");
>       d->number = g_strdup ("9876543210");
>       d->mute = FALSE;
>       
>       printf ("--> %d , %s, %s in %d.\n", d->id, d->name, d->number, d->win);
>       
>       g_hash_table_insert (hash, g_strdup ("1"), d);

Again, the key is likely to be leaked.

>       g_free (d);

Again, this makes the item at key "1" invalid (pointer to
freed memory).

>       printf ("done inserting..... \n");
> 
>       g_hash_table_foreach (hash, print_hash_kv, NULL);
> 
>       return 0;
> }
> 
> The thing is that the output is quite annoying:
> --> 2 , client1, 0123456789 in 3. 
> --> 1 , client2, 9876543210 in 2.
> done inserting.....
> <-- 1 -> 0 , client2, 9876543210 in 2.
> <-- 2 -> 0 , client2, 9876543210 in 2.

The memory block orignially allocated for c (and then freed)
was reused for d.  After d was freed too it was not reused
for anything else yet -- you'd get totally bogus values then.

> My question is how do I manage to get the hash table to actually give me 
> back all the my inserts

Don't destroy them.

Yeti


--
That's enough.
_______________________________________________
gtk-app-devel-list mailing list
gtk-app-devel-list@gnome.org
http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list

Reply via email to