2

したがって、私がやろうとしているのはポインターを解放することだけで、「無効なアドレス」というエラーが表示されます。私が入れたプリントに示されているように、アドレスは明らかに有効ですが、ポインターのアドレスを解放しようとしますが、それでも失敗します。valgrind を介して、アドレスがスレッド 1 のスタック上にあるというエラー無効な free() が表示されますか? 以下のコードは実行可能です。誰でも助けることができますか?

#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;
}
4

2 に答える 2

5

これは壊れています:

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

必要なメモリの量は、保存する必要があるもの、つまり文字列に基づいています。あなたがしたい:

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

または、さらに良いことに、単に使用しますstrdup

于 2012-10-24T00:18:32.130 に答える
3

free()変数をスタックしようとしています: num2(in main()):

int num2 = 3;

後で、次の呼び出しがあります。

printf("put %s: %d\n","test",put(t, "test", &num2));

num2のアドレスをtoに渡しています。これは、後でそれを解放しようと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ため、2 回解放しています。test

于 2012-10-24T00:24:51.190 に答える