我试图使用哈希表来实现单词词典,所以我需要将它全局化,并在我的一个头文件中声明它
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(一个检测内存泄漏的调试器)时,它表示没有内存泄漏是可能的,但它表示存在错误< i>未分配的值是由堆分配创建的,并将我重定向到确切的行,我在那里为dictionary
分配了我已编写的加载函数的确切第一行的内存上面。
我做错了什么?我想全局使用dictionary
的方式是错误的,那么有人可以提出一些其他方法来保持全局并避免这种错误吗?
答案 0 :(得分:7)
在更新的代码中,您使用未初始化的指针:
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;
答案 1 :(得分:4)
您分配给dictionary
的堆分配使用malloc
,它不会初始化返回的字节。因此,您发布的代码中的dictionary
最终会成为一个未初始化的指针数组。大概你继续以某种方式使用那些指针,valgrind知道这是一个错误。
解决此问题的一种简单方法是使用calloc
而不是malloc
,因为它会为您返回返回的字节。或者,使用memset
自己将字节归零。