2012-02-24 35 views
1

我已经实现了如下的散列表结构(读取文本文件中的所有单词,并构造散列表,然后在单行上打印表的所有值):C散列表实现中的内存泄漏

#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的表示为: 总堆的使用情况:在1块

568个字节你能:7个allocs,6周的FreeS,604个字节分配 仍可达也许是现货,我应该还是自由的,或者我做错了什么?非常感谢。

回答

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); 
} 
+0

因为它试图进行第一的malloc之前释放这将失败。相反,将声明更改为初始化键为NULL,并使free()调用有条件。 – mah 2012-02-24 17:03:24

+0

@Seth Carnegie:如果我补充一点,我会得到“指针被释放并没有被分配” – rize 2012-02-24 17:04:30

+0

@mah:你能更准确一些:我应该在哪里设置键为NULL? – rize 2012-02-24 17:07:55

-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 ? */ 
     } 
    } 
}