所以我要做的就是释放一个指针,它只是给我错误'无效地址';虽然地址显然是有效的,如我输入的打印件所示。它试图释放指针的地址,但仍然失败。通过valgrind,它给出错误无效free()说地址在线程1的堆栈上?下面的代码是可运行的;有人可以帮忙吗?
#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;
}
显示错误的测试文件:
#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;
}
答案 0 :(得分:5)
这是破碎的:
char *new = malloc(sizeof(char *));
您需要的内存量取决于您需要存储的内容,即字符串。你想要:
char *new = malloc(strlen(str) + 1);
或者,更好的是,只需使用strdup
。
答案 1 :(得分:3)
您正在尝试free()
堆栈变量:num2
(在main()
中):
int num2 = 3;
稍后,你有这个电话:
printf("put %s: %d\n","test",put(t, "test", &num2));
您将num2
的地址传递给put()
,这意味着remove_entry()
稍后会尝试将其释放。这是非法的。您无法释放堆栈上分配的变量。您应该动态分配num2
:
int* num2 = malloc(sizeof(int));
*num2 = 3;
但是还有另一个问题。在这段代码中:
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);
}
您正在释放curr->value
两次,因为您正在释放test
这只是指针的副本。