I am coding a hash table with singly linkedList and I have this problem free(): double free detected in tcache 2
I tried to fix it but did'nt make it, the problem its the free()
, so could you explain me why I have it, So if anyone can help, so please help me, I'm trying to fix it for hours now...
Thank you.
I've watched some video on youtube and many topics on websitte and also here but I didn't find a solution for mine.
This are my functions:
/**** c file */
/*
some functions here
.
.
.
*/
strhash_table * strhash_table_destroy(strhash_table * table)
{
unsigned int i;
super_list *list;
s_node *node;
for (i = 0; i < table->len; i ) {
list = table->list i;
for (node = list->node; node != NULL; node = node->next) {
free(node->data);
}
list_destroy(list->node);
}
free(table->list);
free(table);
return table;
}
strhash_table * strhash_table_free(strhash_table * table)
{
unsigned int i;
super_list *list;
for (i = 0; i < table->len; i ) {
list = table->list i;
if (list->len > 0) {
free(list->node->data);
list_destroy(list->node);
list->len = 0;
return table;
}
}
return table;
}
strhash_table * strhash_table_remove(strhash_table * table, char * str)
{
const int index = hashCode(str, table->len);
if (table->list[index].len == 0) return table;
s_node *find_node;
const int result = list_process(table->list[index].node, &find_str_node, str, &find_node);
if (result == 1) {
free(find_node->data);
table->list[index].node = list_remove(table->list[index].node, find_node->data);
table->list[index].len--;
}
return table;
}
/**** test file */
strhash_table * test_init(const unsigned int len)
{
strhash_table * table = strhash_table_init(len);
if (!table) {
printf(RED"Tha HashTable hasn't been created\n"reset);
assert(0);
}
printf(GRN"***Tha HashTable has been created***\n"reset);
return table;
}
strhash_table * test_destroy(strhash_table * table){
table = strhash_table_destroy(table);
if (table->list->node) {
printf(RED"The HashTable hasn't been destroyed (%p)\n"reset, table->list->node);
assert(0);
}
printf(GRN"The HashTable has been destroyed\n"reset);
return NULL;
}
int main(void)
{
strhash_table * table =strhash_table_init(10);
strhash_print(table);
strhash_table_add(table, "ele1");
strhash_table_add(table, "ele2");
strhash_table_add(table, "ele3");
strhash_table_add(table, "ele4");
strhash_table_add(table, "ele5");
//strhash_table_remove(table,"ele1");
//strhash_table_free(table);
test_destroy(table);
return 0;
}
Thank you in advance ^^
CodePudding user response:
You should move list_destroy(list->node);
outside the inner loop. You are freeing the node list multiple times inside a loop where you iterate on the node links.
Here is a modified version:
strhash_table *strhash_table_destroy(strhash_table *table) {
unsigned int i;
super_list *list;
s_node *node;
for (i = 0; i < table->len; i ) {
list = table->list i;
for (node = list->node; node != NULL; node = node->next) {
free(node->data);
}
list_destroy(list->node);
}
free(table->list);
free(table);
return table;
}
void list_destroy(s_node *head) {
while (head) {
head = list_headRemove(head);
}
}
s_node *list_headRemove(s_node *head) {
if (!head) return head;
s_node *n = head->next;
free(head);
return n;
}
UPDATE
In the code posted, there are conflicting versions of functions list_destroy
and list_headRemove
, furthermore there are 2 calls to free(node);
in the second function list_destroy
, both of which are useless since node
is a null pointer when the while
loop exits.
UPDATE 2
There is a problem in strhash_table_free
: you free list->node
but you do not update list->node
, so the list is freed a second time in strhash_table_destroy
where list->len
is not tested.
The field len
in super_list
seems redundant. You should just test if the node
member is NULL
and set it to NULL
when the list is freed.
CodePudding user response:
A cleaner way to do it in my opinion assuming you don't reuse list_headRemove
and list_headRemove
:
strhash_table *strhash_table_destroy(strhash_table *table) {
unsigned int i;
super_list *list;
s_node *node, *next;
for (i = 0; i < table->len; i ) {
list = table->list i;
node = list->node;
while (node) {
next = node->next;
free(node->data);
free(node);
node = next;
}
}
free(table->list);
free(table);
return table; /* This pointer is not valid anymore be careful */
}