【发布时间】:2019-05-21 06:47:06
【问题描述】:
很抱歉,如果以下问题看起来很幼稚,我对编程很陌生,但仍然在基本概念上挣扎。
我编写了一个代码,将字典(txt 文件)加载到哈希表/链表数据结构中,程序编译并提供预期结果,但 Valgrind 显示内存泄漏。所有主要功能(创建节点、填充、搜索、打印)都可以正常工作,除了破坏功能(用于从 malloc 中释放内存的功能)。 Valgrind 显示内存泄漏。
我在这里缺少什么?如何让我的代码更干净?
感谢您的宝贵时间!你太棒了!
我知道,至少部分原因是我填充数据结构的方法 - 我使用 2 个 char* 缓冲区(tmp 和 tmp1,循环内部和外部)来处理来自 fscanf 的输入到节点中。我想在卸载期间我可以在外部缓冲区(“tmp”)上使用“免费”功能,但不能在内部缓冲区(“tmp1”)上使用。
我尝试使用 1 个缓冲区(循环内部和外部)和 2 个静态初始化的缓冲区(char tmp[])。两种方法都只用 1 个单词(字典中的最后一个单词)填充结构。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//定义节点结构
typedef struct node
{
char* word;
struct node* next;
}node;
//散列大小变量和散列函数(感谢K&R)
const int hash_elements = 100;
unsigned hash(char *s)
{
unsigned hashval;
for (hashval = 0; *s != '\0'; s++)
hashval = *s + 31 * hashval;
return hashval % hash_elements;
}
// 将节点添加到 ll 开头的函数
int addnode_start (node** head, char* word)
{
node* new_node = malloc(sizeof(node));
if (new_node == NULL)
{
return 1;
}
new_node->word = word;
new_node->next = *head;
*head = new_node;
return 0;
}
//释放分配内存的函数
void destroy (node* hashtable)
{
if (hashtable == NULL)
{
return;
}
else
{
destroy(hashtable->next);
free(hashtable);
}
}
// MAIN FUNCTION - 将 txt 文件中的单词字符串放入哈希表/链表数据结构中
int main (int argc, char* argv[])
{
if (argc < 2)
{
printf("Usage: ./stringdll dictionary.txt\n");
return 1;
}
// 为链表(哈希表)创建一个数组并为头分配内存
node* hashtable[hash_elements];
for (int i = 0; i < hash_elements; i++)
{
hashtable[i] = malloc(sizeof(node));
if (hashtable[i] == NULL)
{
return 1;
}
}
//打开字典文件进行阅读
char* infile = argv[1];
FILE* input = fopen(infile, "r");
if (input == NULL)
{
printf("File does not exist.\n");
return 1;
}
// 为字符串定义临时存储
char* tmp = malloc(41);
// 扫描文件中的字符串并填充链表
while(fscanf(input, "%s", tmp) != EOF)
{
char* tmp1 = malloc(41);
for (int h = 0; h < hash_elements; h++)
{
if (hash(tmp) == h)
{
if (hashtable[h]->word == '\0')
{
hashtable[h]->word = strcpy(tmp1, tmp);
hashtable[h]->next = NULL;
}
else
{
int tmp_0 = addnode_start(&hashtable[h], strcpy(tmp1, tmp));
if (tmp_0 == 1)
{
return 1;
}
}
}
}
}
// 卸载字典
for (int d = 0; d < hash_elements; d++)
{
destroy (hashtable[d]);
}
return 0;
}
我希望 Valgrind 显示在我的程序工作期间没有内存泄漏。
【问题讨论】:
-
你没有
fclose你的文件。你永远不会freetmp和tmp1。 -
我不明白这个问题,valgrind 会准确地告诉你你没有发布什么——释放它们。
-
您没有释放存储在哈希表中的单词。
-
你的数组是一个节点的数组。它可以是指向节点的 指针 数组,指向链的头部。 (并初始化为 NULL)
标签: c linked-list hashtable