为什么我的节点都没有被释放? (cs50 pset5分段错误)C

时间:2015-10-09 05:31:55

标签: c memory-leaks segmentation-fault cs50

我无法在哈佛大学的cs50课程的pset5中实现我的加载和卸载功能。当我运行它时,我得到一个分段错误,当我运行valgrind时,它告诉我没有任何我在加载时malloc的节点被释放。

我一直试图解决这个问题好几天,我已经为我的卸载功能尝试了几种不同的实现,但没有任何效果。我认为错误可能出在我的加载功能中。有人请请帮我这个吗?

 /****************************************************************************
 * dictionary.c
 *
 * Computer Science 50
 * Problem Set 5
 *
 * Implements a dictionary's functionality.
  ***************************************************************************/

 #include <stdbool.h>
 #include <stdio.h>
 #include <ctype.h>
 #include <stdlib.h>
 #include <math.h>
 #include <string.h>

 #include "dictionary.h"

 #define HASHTABLE_SIZE 5000

 // create word counter for size
 int wordCount = 0;

 // linked link struct
 typedef struct node
 {
     // word's length + NULL character
     char word[LENGTH + 1];
     struct node* next;
 }
 node;

 // Hashtable array
 node* hashtable[HASHTABLE_SIZE];


 // hash function from study.cs50.net
 int hash_function(char* key)
 {
     // initialize index to 0
     int index = 0;   

     // sum ascii values
     for (int i = 0; key[i] != 0; i++)
     {
         index += toupper(key[i]) - 'A';
     }

     return index % HASHTABLE_SIZE;
 }

 /**
  * Returns true if word is in dictionary else false.
  */
 bool check(const char* word)
 {
     // create variable to hold word
     char temp[LENGTH + 1];

     // convert every character in word to lowercase
     for (int i = 0, n = strlen(word); i < n; i++)
     {
         if (isalpha(word[i]))
         {
             temp[i] = tolower(word[i]);  
         } 
     }

     // get hashed word's index
     int hash_index = hash_function(temp);

     // find head of that index
     node* head = hashtable[hash_index];


     // traverse through linked list 
     for (node* cur = head; cur != NULL; cur = cur->next)
     {
         // find if linnked list contains word
         if (strcmp(cur->word, word) == 0)
         {
             return true;
         }   
     }  

     return false;
 }

 /**
  * Loads dictionary into memory.  Returns true if successful else false.
  */
 bool load(const char* dictionary)
 {
     // // open file
     FILE* file = fopen(dictionary, "r");

     // check if file exists
     if (file == NULL)
     {
         return false;
     }

     // word length plus NULL character
     char word[LENGTH + 1];

     // iterate through every word of the dictionary
     while (fscanf(file, "%s\n", word) != EOF) // Source: http://stackoverflow.com/questions/6275558/question-about-whileeof
          {
              node* new_node = malloc(sizeof(node));

         if (new_node == NULL)
         {
             return false;
         }

         wordCount++;

         strcpy(new_node->word, word);  // Source: cs50 reddit

         int hash_index = hash_function(new_node->word);

         // check whether node should be head
         if (hashtable[hash_index] == NULL)
         {
             hashtable[hash_index] = new_node;
             new_node->next = NULL;
         }

         else
         {
             new_node->next = hashtable[hash_index];
             hashtable[hash_index] = new_node; 
         }    
     }
     // close file
     fclose(file);

     return false;
 }

 /**
  * Returns number of words in dictionary if loaded else 0 if not yet loaded.
  */
 unsigned int size(void)
 {

     return wordCount;
 }

 /**
  * Unloads dictionary from memory.  Returns true if successful else false.
  */
 bool unload(void)
 {   
     // go through all of the indexes in the hashtable 
     for (int i = 0; i < HASHTABLE_SIZE; i++)
     {
         node* head = hashtable[i];

         while (head != NULL)
         {
             node* ptr = head->next;

             free(head);
             head = ptr;
         }   
     }   
     return true;
 }

1 个答案:

答案 0 :(得分:2)

您的unload功能很好。您的代码的问题是check函数,特别是您尝试将输入转换为小写的部分:

char temp[LENGTH + 1];

for (int i = 0, n = strlen(word); i < n; i++)
{
    if (isalpha(word[i]))
    {
        temp[i] = tolower(word[i]);  
    } 
}

这里有两个问题。首先,temp不是以空值终止的。其次,检查isalpha表示您可以保留字符未初始化:如果您的输入是"I'm"temp将保留'I'垃圾'm'垃圾应该包含'I'' \'''m''\0'垃圾

或者,您可以过滤掉不需要的字符。在这种情况下,您需要两个索引:一个用于源词,另一个用于过滤词。

但是你甚至不需要这个额外的步骤,因为你的哈希函数再次将输入转换为toupper

说到你的哈希函数:你可能想要选择一个更好的哈希函数。当前的值不会在5000个插槽中很好地分配值。 (当你添加时,你甚至会达到5000,什么?在0到25之间最多20个数字?)

哈希还有另一个问题:如果你输入一个数字,贡献的“字母”是负数,因为在ASCII中,数字的值从48到57,你从中减去'A',65的值他们。通常,您的哈希函数应返回无符号值。

相关问题