Search code examples
cfree

Segmentation fault when freeing at specific indices


Following this tutorial on Hash Tables, I implemented a sort of simplified version. However, whenever delete_entry is called on every 4th index(4,8,12...), I get a segmentation fault. Else, it works fine

Here's the code I run:

#include <stdio.h>

typedef struct {
    int key;
    int value;
} entry;

typedef struct{
    int length;
    int count;
    entry** items;
} table;

entry *new_entry(const int, const int);
table *create_table();
void destroy_table(table *t);
void delete_entry(entry *e);
void table_insert(table *, const int, const int);

int main(){
    table *new_table = create_table();
    printf("[INFO] Created new table successfully!!\n");
    
    for(int i=0; i<16; i++){
        table_insert(new_table,i,i+i);
    }
    printf("[INFO] Inserted %d items\n",new_table->count);

    destroy_table(new_table);
    printf("[INFO] Destroyed table successfully!!\n");
    return 0;

}

table *create_table(){
    table *new_table = malloc(sizeof(table));
    if(new_table == NULL){
        printf("[WARNING] Malloc failure, returning NULL");
        return NULL;
    }
    new_table->length = 16;
    new_table->count = 0;
    new_table->items = calloc((size_t)new_table->length, sizeof(entry*));
    
    return new_table;
}

entry *new_entry(const int k, const int val){
    entry *new_item = malloc(sizeof(entry));
    if(new_item == NULL){
        printf("[WARNING] Malloc failure, returning NULL");
        return NULL;
    }
    new_item->key = k;
    new_item->value = val;
    
    return new_item;
}
void destroy_table(table *t){
    for(int i=0; i<t->count; i++){
        if(i== 4 || i == 8|| i==12) //Without this program terminates after 3rd index
            continue;
        entry *e = t->items[i];
        if (e != NULL){
            delete_entry(e);
        }
    }
    free(t->items);
    free(t);
}
void delete_entry(entry *e){
    free(e->key);
    free(e->value);
    free(e);
}

void table_insert(table *t, const int k, const int v){
    entry *e = new_entry(k, v);
    t->items[t->count] = e;
    t->count++;
}

Solution

  • Try to replace delete_entry() with:

    void delete_entry(entry *e){
        free(e);
    }
    

    Freeing values of integers e->key and e->value will likely result in Undefined Behavior. You should use free() only on objects produced by malloc() and friends.