C 在拼写检查器中使用大小为8的未初始化值
我编写了一个拼写检查器,它使用trie来存储和检查拼写错误的单词。它将文本文件字典加载到内存中,接受单词以检查拼写错误,并卸载内存。程序编译成功,但运行时会产生分段错误。基于valgrind,问题似乎是在我的插入函数中使用了未初始化的值C 在拼写检查器中使用大小为8的未初始化值,c,memory-leaks,C,Memory Leaks,我编写了一个拼写检查器,它使用trie来存储和检查拼写错误的单词。它将文本文件字典加载到内存中,接受单词以检查拼写错误,并卸载内存。程序编译成功,但运行时会产生分段错误。基于valgrind,问题似乎是在我的插入函数中使用了未初始化的值 //If word not present, inserts word into trie //If the word is a prefix of a node, marks the "leaf node" (end-of-word node) void in
//If word not present, inserts word into trie
//If the word is a prefix of a node, marks the "leaf node" (end-of-word node)
void insert(struct node *root, const char *word)
{
int length = strlen(word);
int index = 0;
//start from root node
struct node *tempNode = root;
for(int i = 0; i < length; i++)
{
//if the current letter in word is a letter
if(word[i] != '\'')
//convert the alphabet to it's respective index number
index = CHAR_TO_INDEX(tolower(word[i]));
else
//assign index number 27 (for apostrophe)
index = INPUT_SIZE;
//create a new node if path doesn't exist (is NULL)
if(!(tempNode->children[index]))
tempNode->children[index] = getNode();
//go to next node
tempNode = tempNode->children[index];
}
//mark last node as leaf
tempNode->isWord = true;
}
和getNode(),创建初始化为NULL的新节点:
//Returns new trie node initialised to NULL
struct node *getNode(void)
{
//initialise new node
struct node *newNode = NULL;
newNode = malloc(sizeof(struct node));
//proceed if enough memory to allocate
if(newNode)
{
//initialise pointers
for(int i = 0; i < INPUT_SIZE; i++)
newNode->children[i] = NULL;
newNode->isWord = false;
}
else return false;
return newNode;
}
valgrind在--leak check=full、--leak check=full和--show leak kinds=all的情况下运行。我曾尝试引用以前文章中类似的错误,但上下文的差异使我很难确定应该做什么。第84行的内容是if(!(tempNode->children[index])。(在我看来)这似乎是问题的根源
谢谢大家!
while((ch = fgetc(file)) != '\n')
{
word[counter] = ch;
counter++;
}
//whole word found, insert word and reset counter, increment word count
insert(root, word);
这是导致未定义行为的代码部分
您的字符串word
不是以null结尾的,但是insert
希望它是以null结尾的(因为它做的第一件事是调用strlen
,它需要以null结尾的字符串)
简单的解决办法是
word[counter] = '\0';
在调用
insert
之前,假设所有内容都在边界内。调试器可能会告诉您的更多什么是结构节点?子节点是指针数组吗?这里可能有帮助。我在中添加了结构节点的定义。谢谢你的提问@伊兰
Conditional jump or move depends on uninitialised value(s)
==9334== at 0x4011DD: insert (dictionary.c:84)
==9334== by 0x4014D1: load (dictionary.c:188)
==9334== by 0x40095D: main (speller.c:40)
==9334== Uninitialised value was created by a heap allocation
==9334== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9334== by 0x4010CB: getNode (dictionary.c:40)
==9334== by 0x4011E7: insert (dictionary.c:85)
==9334== by 0x4014D1: load (dictionary.c:188)
==9334== by 0x40095D: main (speller.c:40)
==9334==
==9334== Use of uninitialised value of size 8
==9334== at 0x4011D5: insert (dictionary.c:84)
==9334== by 0x4014D1: load (dictionary.c:188)
==9334== by 0x40095D: main (speller.c:40)
==9334== Uninitialised value was created by a heap allocation
==9334== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9334== by 0x4010CB: getNode (dictionary.c:40)
==9334== by 0x4011E7: insert (dictionary.c:85)
==9334== by 0x4014D1: load (dictionary.c:188)
==9334== by 0x40095D: main (speller.c:40)
==9334==
==9334== Invalid read of size 8
==9334== at 0x4011D5: insert (dictionary.c:84)
==9334== by 0x4014D1: load (dictionary.c:188)
==9334== by 0x40095D: main (speller.c:40)
==9334== Address 0x91 is not stack'd, malloc'd or (recently) free'd
==9334==
==9334==
==9334== Process terminating with default action of signal 11 (SIGSEGV)
==9334== Access not within mapped region at address 0x91
==9334== at 0x4011D5: insert (dictionary.c:84)
==9334== by 0x4014D1: load (dictionary.c:188)
==9334== by 0x40095D: main (speller.c:40)
while((ch = fgetc(file)) != '\n')
{
word[counter] = ch;
counter++;
}
//whole word found, insert word and reset counter, increment word count
insert(root, word);
word[counter] = '\0';