user994165
user994165

Reputation: 9512

GLib Hash Table not returning correct value

I added several key, value pairs to my GLib hash table, which is under my memory struct. The key is a (char *) pointer returned from a malloc. The value is the size malloc allocated.

void addstomemstruct(struct memory *mem, char *key_address, size_t sz) {
    g_hash_table_insert(mem->singleton, key_address, &sz);
    printf("** retrieving size: %Zu add=%p\n",(*(size_t*) g_hash_table_lookup(mem->singleton, key_address)), key_address);
}

Later on, when I went to retrieve the value based on the value based on the key, the returned size (value) is always 10, which was the last value I added to the hash table

size_t get_blocksize(GHashTable *hashtable, char *key_address, size_t *result_flag)
{   size_t *sz_ptr = (size_t *) g_hash_table_lookup(hashtable, key_address);
    ...

char *logmsg;asprintf(&logmsg,"In get_blocksize: *sz_ptr=%Zu\n",*sz_ptr);
    log_msg(logmsg);

printf("** retrieving size: %Zu add=%p\n",(*(size_t*) g_hash_table_lookup(hashtable, key_address)), key_address);
...
}

Printout:

preparing to add pointer: 0x9b52f10
** adding size: 1
** retrieving size: 1 add=0x9b52f10
preparing to add pointer: 0x9b52f48
** adding size: 2
** retrieving size: 2 add=0x9b52f48
preparing to add pointer: 0x9b52f58
** adding size: 3
...
preparing to add pointer: 0x9b52fc8
** adding size: 10
** retrieving size: 10 add=0x9b52fc8

then later when I try to retrieve the first value:

In get_blocksize: *sz_ptr=10
** retrieving size: 10 add=0x9b52f10
Freed address 0x9b52f10.  Size: 10. mem->stats->active_count=9, mem->stats->active_size=45.

Upvotes: 0

Views: 264

Answers (1)

rkhayrov
rkhayrov

Reputation: 10260

You are passing a pointer to an automatic storage duration variable (function parameter) as a hash table value. When it goes outside of the scope, it's an undefined behavior to access it.

You can either:

  • Allocate storage for sz with malloc/gnew and register an appropriate value_destroy_func at hash table creation.
  • Take advantage of the fact that size_t value fits in a pointer and cast it to gpointer. Technically this an UB, but should work on most platforms. Probably should not do this unless small object allocation is identified as a bottleneck.

Upvotes: 3

Related Questions