【问题标题】:Memory leak in C hash table implementationC 哈希表实现中的内存泄漏
【发布时间】:2012-03-15 03:21:49
【问题描述】:

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

#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 次分配,6 次释放,604 字节分配 仍然可达:1 个块中 568 个字节

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

【问题讨论】:

    标签: c memory-leaks hashtable


    【解决方案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);
    }
    

    【讨论】:

    • 这将失败,因为它会在执行第一个 malloc 之前尝试释放。相反,将声明更改为将 key 初始化为 NULL,并使 free() 调用有条件。
    • @Seth Carnegie:如果我添加它,我会得到“未分配指针被释放”
    • @mah:你能说得更准确点吗:我应该在哪里将 key 设置为 NULL?
    • @rize 初始化时:char* key = NULL;
    • @rize 你不必做if (key) free(key); 因为你可以在NULL 指针上调用free,它会非常好并且什么都不做。当key 不是NULL 并且 它指向一些没有用malloc 分配的内存(或者由malloc 分配但已经是freed)和你打电话给free就可以了。
    【解决方案2】:
    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 ? */
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-09
      • 2021-08-21
      • 1970-01-01
      • 2019-05-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多