C哈希表实现中的内存泄漏

时间:2012-02-24 16:55:10

标签: c memory-leaks hashtable

我已经实现了如下的哈希表结构(从文本文件中读取所有单词,并构造一个哈希表,然后在一行上打印表的所有值):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

unsigned int hashf(const char *buf, size_t len) {
    unsigned int h = 0;
    size_t i;
    for (i = 0; i < len; i++) {
        h += buf[i];
        h += h << 10;
        h ^= h >> 7;
    }
    h += h << 3;
    h ^= h >> 11;
    h += h << 15;
    return h;
}

void destroy_hash(char *hashtable[], int table_size) {
    int i;
    for (i=0; i<table_size; i++) {
        if (hashtable[i]) {
            free(hashtable[i]);
        }
    }
}

int main(int argc, char *argv[])
{
    if (argc != 3) {
        printf("Invalid parameters!\n");
        return EXIT_FAILURE;
    }
    const char *filename = argv[1];
    int table_size = atoi(argv[2]);

    char *hashtable[table_size];
    int i;
    for (i = 0; i < table_size; i++) {
        hashtable[i] = NULL;
    }
    unsigned int h, h_k;

    FILE *fileread = fopen(filename, "r");

    char *key;
    char buf[100];
    int probe_nro, word_nro = 0;

    if (fileread) {

        fscanf(fileread, "%99s", buf);
        key = malloc((strlen(buf)+1)*sizeof(char));
        memcpy(key, buf, strlen(buf) + 1);
        while(!feof(fileread)) {
            // Increase word_nro by 1
            word_nro += 1;
            if (word_nro <= table_size) {
                h = hashf(key, strlen(buf)) % table_size;
                if (!hashtable[h]) {
                    hashtable[h] = key;
                }
                else {
                    // Begin probing
                    probe_nro = 1;
                    // Save original hash to h_k:
                    h_k = h;

                    h = (h_k+(probe_nro*probe_nro)) % table_size;

                    while (hashtable[h] && (probe_nro <= 10000)) {
                        probe_nro += 1;
                        h = (h_k+(probe_nro*probe_nro)) % table_size;
                    }
                    // If no vacancy found after 10000 probes, return error
                    if (probe_nro == 10000) {
                        printf("Error: table full\n");
                        free(key);
                        destroy_hash(hashtable, table_size);
                        return(1);
                    }
                    hashtable[h] = key;
                }
                fscanf(fileread, "%99s", buf);
                if (!feof(fileread)) {
                    key = malloc((strlen(buf)+1)*sizeof(char));
                    memcpy(key, buf, strlen(buf) + 1);
                }
            }
        else {
            free(key);
            printf("Error: table full\n");
            destroy_hash(hashtable, table_size);
            return(1);
        }
    }
    for (i=0; i < table_size; i++) {
        if (hashtable[i]) {
            printf("%s", hashtable[i]);
        }
        else {
            printf(" ");
        }
        if (i < table_size - 1) {
            printf(",");
        }
    }
    printf("\n");
    destroy_hash(hashtable, table_size);
}
else    {
    printf("Can't open file!\n");
    return(1);
}
return(0);
}

我找不到内存泄漏,这在valgrind中表示为: 总堆使用量:7个allocs,6个frees,604个字节分配 仍然可以访问:1个块中的568个字节

你可以发现,我还应该释放什么,或者我做错了什么?非常感谢。

2 个答案:

答案 0 :(得分:1)

在这一行

if (!feof(fileread)) {
    key = malloc((strlen(buf)+1)*sizeof(char));
    memcpy(key, buf, strlen(buf) + 1); // <--
}

您正在使key指向新位置,而不会释放您使用malloc分配的旧内存。它应该是

if (!feof(fileread)) {
    free(key); // <--
    key = malloc((strlen(buf)+1)*sizeof(char));
    memcpy(key, buf, strlen(buf) + 1);
}

答案 1 :(得分:-1)

void destroy_hash(char *hashtable[], int table_size) {
    int i;
    for (i=0; i<table_size; i++) {
        if (hashtable[i]) {
            free(hashtable[i]);
            hashtable[i] = NULL; /* this one ? */
        }
    }
}