我正在尝试使用哈希表实现单词词典,所以我需要将其全局化,并在我的一个头文件中声明它
extern node** dictionary;
节点在哪里
typedef struct node
{
char* word;
struct node* next;
} node;
然后在另一个定义了函数的文件中,我包括具有字典声明的标头,并且还在顶部添加
node** dictionary;
然后在实际加载字典的函数中,我首先为将构成哈希表的链表分配内存
bool load(const char* dict_file)
{
dictionary = malloc(sizeof(node*) * LISTS);
FILE* dict = fopen(dict_file, "r");
if(dict == NULL)
return false;
char buffer[MAX_LEN + 2];
size_dict = 0;
while(fgets(buffer, MAX_LEN + 2, dict) != NULL)
{
node* new_node = malloc(sizeof(node));
int len = strlen(buffer);
new_node->word = malloc(sizeof(char) * (len));
//avoid \n
for(int i = 0; i < len - 1; i++)
new_node->word[i] = buffer[i];
new_node->word[len - 1] = '\0';
new_node->next = NULL;
int index = hash(buffer);
new_node->next = dictionary[index];
dictionary[index] = new_node;
size_dict++;
}
if (ferror(dict))
{
fclose(dict);
return false;
}
fclose(dict);
return true;
}
所以程序运行正常,然后释放所有分配给字符串和节点的内存,当我运行valgrind(检测内存泄漏的调试器)时,它说不可能发生内存泄漏,但是它说有错误未初始化的值是由堆分配创建的,并将我重定向到确切的行,在这里我为dictionary
分配的内存是我上面编写的加载函数的确切第一行。我究竟做错了什么?我想我在全局上使用dictionary
的方法是错误的,所以有人可以建议将其保持在全局状态并避免此错误的其他方法吗?
在更新的代码中,您使用未初始化的指针:
dictionary = malloc(sizeof(node*) * LISTS);
// .... code that does not change dictionary[i] for any i
new_node->next = dictionary[index]; // use uninitialized pointer
正如人们已经写过的,只有在进入此循环之前将所有指针都设置为NULL
时,此方法才有效:
dictionary = malloc(sizeof(node*) * LISTS);
if ( !dictionary ) {
return false;
}
for (size_t i = 0; i < LISTS; ++i) {
dictionary[i] = NULL;
}
您分配给dictionary
的堆分配使用malloc
,它不会初始化返回的字节。因此,您发布的代码中的dictionary
最终是未初始化指针的数组。大概您会以valgrind知道是错误的某种方式继续使用那些指针。
解决此问题的一种简便方法是使用calloc
而不是malloc
,因为它会为您将返回的字节清零。或者,使用memset
自行将字节清零。