So all I'm trying to do is free a pointer and it just gives me the error 'invalid address'; though the address is clearly valid, as illustrated by the prints I put in. It tries to free the address of the pointer, but still fails. Through valgrind, it gives the error invalid free() saying the address is on thread 1's stack? The code below is runnable; can anyone help?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#define SUCC 1
#define FAIL -1
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;
extern unsigned int hash_code(const char *key) {
unsigned int hash = 0, i = 0;
while(i < strlen(key)) {
hash ^= ((hash << 3) | (hash >> 29)) + key[i++];
}
return hash;
}
/*Makes copy of string and returns pointer to it*/
char * cpy(const char *str) {
char *new = malloc(sizeof(char *));
if(new)
strcpy(new, str);
return new;
}
int create_table(Table ** table, int table_size, void (*free_value)(void *)) {
*table = malloc(sizeof(Table));
if(table && table_size != 0) {
int i = 0;
(*table)->key_count = 0;
(*table)->table_size = table_size;
(*table)->free_value = free_value;
(*table)->buckets = calloc(table_size, sizeof(Bucket *));
while(i < table_size)
(*table)->buckets[i++] = NULL;
return SUCC;
}
return FAIL;
}
int put(Table * table, const char *key, void *value) {
if(table && key) {
int hash = hash_code(key)%table->table_size;
Bucket *curr = table->buckets[hash];
while(curr) {
if(strcmp(curr->key, key) == 0) {
if(table->free_value)
table->free_value(curr->value);
printf("addr of ptr: %p\n", value);
curr->value = value;
printf("addr of curr ptr: %p\n", curr->value);
return SUCC;
}
curr = curr->next;
}
curr = malloc(sizeof(Bucket));
curr->key = cpy(key);
printf("addr of ptr: %p\n", value);
curr->value = value;
printf("addr of curr ptr: %p\n", curr->value);
curr->next = table->buckets[hash];
table->buckets[hash] = curr;
table->key_count++;
return SUCC;
}
return FAIL;
}
int remove_entry(Table * table, const char *key) {
if(table && key) {
int hash = hash_code(key)%(table->table_size);
Bucket *curr = table->buckets[hash], *prev = table->buckets[hash];
while(curr) {
printf("attempt");
if(strcmp(curr->key, key) == 0) {
void * test = curr->value;
printf("at addr %p\n", test);
table->free_value(test);
printf("freed");
if(table->free_value){
table->free_value(curr->value);
}
free(curr->key);
curr->key = NULL;
curr->value = NULL;
table->key_count--;
if(prev == curr)
table->buckets[hash] = curr->next;
else
prev->next = curr->next;
free(curr);
curr = NULL;
return SUCC;
}
prev = curr;
curr = curr->next;
}
}
return FAIL;
}
And the test file that shows the error:
#include <stdio.h>
#include <stdlib.h>
#include "htable.h"
int main() {
Table *t;
int num2 = 3;
printf("create: %d\n",create_table(&t, 2, free));
printf("addr of ptr: %p\n",(void *)&num2);
printf("put %s: %d\n","test",put(t, "test", &num2));
printf("rem key: %d\n",remove_entry(t, "test"));
return 0;
}