
Question:
I'm implementing a hashtable that has a remove_entry function as well as a clear_table function. Right now I'm getting memory read errors pertaining to the remove_entry function. And help would be greatly appreciated
These are my structures:
typedef struct bucket {
char *key;
void *value;
struct bucket *next;
} Bucket;
typedef struct {
int key_count;
int table_size;
void (*free_value)(void *);
Bucket **buckets;
} Table;
Here's my function:
int remove_entry(Table * table, const char *key){
unsigned int hc = 0;
Bucket *curr_b;
Bucket *next_b;
if(table == NULL || key == NULL){
return FAIL;
} else {
hc = hash_code(key)%(table->table_size);
if(table->buckets[hc] != NULL){
curr_b = table->buckets[hc];
/*Check the buckets in linked list*/
while(curr_b != NULL){
next_b = curr_b->next;
if(strcmp(curr_b->key,key) == 0){
free(curr_b->key);
if(table->free_value != NULL){
table->free_value(curr_b->value);
}
free(curr_b);
curr_b = NULL;
table->key_count--;
return SUCC;
} else {
curr_b = next_b;
}
}
return FAIL;
}
return FAIL;
}
}
The memory leaks come after removing an entry, and trying to read the table after. I don't think I removed things right.
Memory errors:
Can't figure out how to copy/paste from terminal, so they all say things like
Invalid read of size __
Address ____ is __ bytes inside a block of size ___ free'd
Answer1:You need to consider the case where table->buckets[hc]
is the bucket you free.
Right before free(curr_b->key);
add:
if(curr_b == table->buckets[hc]) {
table->buckets[hc] = next_b;
}
As it is now, you free a bucket, but table->buckets[hc]
still points to it. So the next time you read it you are reading free'ed memory. Thus the error.
Also, you need to keep track of the <em>previous</em> bucket so you can point the previous bucket to the next bucket when you remove a bucket.