【发布时间】:2016-01-06 22:47:07
【问题描述】:
我在哈佛 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;
}
【问题讨论】:
-
在调试器下运行它时发现了什么? “free”的命中次数和“malloc”的命中次数一样多吗?
-
请出示您的
main函数和/或驱动完整程序的其他代码。否则我们不知道你是否打电话给unload(我不是说你不是,但简单的错误在 StackOverflow 上并不少见)。 -
另外,刚刚想到你的程序可能在任何
free调用完成之前就崩溃了,这就是 valgrind 报告没有释放的原因。如果是这样,那是一个转移注意力的问题,你关注的是错误的事情(泄漏)。而是专注于 segv。一种可能性是你得到了一些长词。您正在使用不安全的函数,例如strcpy和fscanf,没有检查以确保您的缓冲区没有溢出。 -
如果您有分段错误,那么您不太可能到达调用
unload的地步。一个好的调试器会带你找到分段错误的根源。 -
请按照已经建议的方式使用调试器。这应该可以准确地告诉您哪一行代码导致了 segv。如果您需要更多帮助,您需要显示更新的代码(否则我们不知道您的更改是否正确和完整)。但听起来你没有修复
check函数,它仍然存在temp缓冲区溢出的问题。
标签: c memory-leaks segmentation-fault cs50