【问题标题】:Invalid pointer address when trying to free尝试释放时指针地址无效
【发布时间】:2012-10-24 00:16:32
【问题描述】:

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

【问题讨论】:

    标签: c pointers


    【解决方案1】:

    这个坏了:

    char *new = malloc(sizeof(char *));
    

    您需要的内存量取决于您需要存储的内容,即字符串。你想要:

    char *new = malloc(strlen(str) + 1);
    

    或者,更好的是,只需使用strdup

    【讨论】:

    • 不,还是同样的错误。另外,我在值上得到了错误,而不是在键上。但还是做出了改变,谢谢。
    【解决方案2】:

    您正在尝试 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-&gt;value,因为你释放了test,这只是指针的一个副本。

    【讨论】:

    • 好吧,确实解决了这个问题,但代码还有其他问题,因为现在我在 free() 语句中得到“内存在分配块之前被破坏”......感谢您的帮助不过。
    • 是的,当我第一次尝试时,我实际上是想说您的解决方案不起作用,但后来我意识到我没有把测试线拿出来。谢谢
    猜你喜欢
    • 2014-09-08
    • 1970-01-01
    • 2021-10-07
    • 2023-01-22
    • 2017-02-25
    • 2015-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多