我建议用malloc,calloc解决我的问题,或者将子节点分配给NULL,但实际上我做的一切似乎都没有用。我正在研究这个问题已经很久了,以至于我无法将我的大脑包裹在需要发生的事情之中。所以一些帮助将不胜感激 这是我的代码:
typedef struct trie
{
bool is_word;
struct trie* children[27];
}
trie;
trie* root = NULL;
int wordCount = 0;
int trie_pos;
/**
* Returns true if word is in dictionary else false.
*/
bool check(const char* word)
{
trie* current = root;
for (int i = 0; word[i] != '\0'; i++)
{
int letter = tolower(word[i]);
if (word[i] == '\'')
{
letter = 'z' - 'a' + 1;
}
else
{
letter = letter - 'a';
}
if (current -> children[letter] == NULL)
{
return false;
}
else
{
current = current -> children[letter];
}
}
if (current -> is_word == true)
{
return true;
}
else
{
return false;
}
//return false;
}
/**
* Loads dictionary into memory. Returns true if successful else false.
*/
bool load(const char* dictionary)
{
FILE *source = fopen(dictionary, "r");
if (source == NULL)
{
return false;
}
// malloc memory for firstNade
root = malloc(sizeof(trie));
int character = 0;
// use trie* current as cursor
trie* current = NULL;
//loop through dictionary until end of file EOF
while(fgetc(source) != EOF)
{
fseek(source, -1, SEEK_CUR);
// set cursor to firstNode
current = root;
//loop through characters until \n
for (character = fgetc(source); character != '\n'; character = fgetc(source))
{
// if apostrophes, set character to z+1
if (character == '\'')
{
character = 'z' -'a' + 1;
}
else
{
character = character - 'a';
}
// If the character is not in trie...
if (current->children[character] == NULL)
{
// ... malloc a new node and go there
current->children[character] = malloc(sizeof(trie));
current = current->children[character];
}
else // ... but if it is, go to the existing node
{
current = current->children[character];
}
}
current->is_word = true;
wordCount++;
}
fclose(source);
return true;
}
/**
* 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.
*/
void unloadHelper(struct trie* currNode)
{
for(int i = 0; i < 27; i++)
{
if(currNode->children[i] !=NULL)
{
unloadHelper(currNode->children[i]);
}
}
free(currNode);
}
/**
* Unloads dictionary from memory. Returns true if successful else false.
*/
bool unload(void)
{
unloadHelper(root);
return true;
}
这是我的valgrind输出的第一部分:
==24410== Conditional jump or move depends on uninitialised value(s)
==24410== at 0x804912B: load (dictionary.c:106)
==24410== by 0x8048745: main (speller.c:45)
==24410== Uninitialised value was created by a heap allocation
==24410== at 0x4006AB1: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==24410== by 0x804907D: load (dictionary.c:79)
==24410== by 0x8048745: main (speller.c:45)
答案 0 :(得分:3)
valgrind输出非常清楚......您正在访问未初始化的值。
root = malloc(sizeof(trie)); // uninitialized space
// ...
current = root;
现在current->
任何都未初始化。但是你去了:
if (current->children[character]
读取未初始化的变量current->children[character]
。
看起来你的代码假设未初始化的指针是NULL,但它们不是。也许它会修复此问题以添加以下函数:
struct trie *new_node(void)
{
struct trie *node = malloc(sizeof(trie));
if ( !node ) exit(EXIT_FAILURE);
node->is_word = false;
for (size_t i = 0; i < sizeof node->children / sizeof node->children[0]; ++i)
node->children[i] = NULL;
return node;
}
并在想要创建节点时调用它:
root = new_node();
current->children[character] = new_node();