尝试释放时指针地址无效

时间:2012-10-24 00:16:32

标签: c pointers

所以我要做的就是释放一个指针,它只是给我错误'无效地址';虽然地址显然是有效的,如我输入的打印件所示。它试图释放指针的地址,但仍然失败。通过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;
}

2 个答案:

答案 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这只是指针的副本。