【发布时间】:2017-06-19 12:49:00
【问题描述】:
我编写了一个拼写检查器,它使用 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 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;
}
insert(将单词放在 trie 中)由 load 调用(将单词从字典 txt 文件移动到内存中):
bool load(const char *dictionary)
{
//initialise variables
char ch;
char word[LENGTH] = "";
int counter = 0;
struct node *root = getNode();
//open file to start inserting words
FILE *file = fopen(dictionary, "r");
//load words in dictionary into memory
while (EOF)
{
while((ch = fgetc(file)) != '\n')
{
word[counter] = ch;
counter++;
}
//whole word found, insert word and reset counter, increment word count
insert(root, word);
counter = 0;
word_Count++;
}
//close all open files if EOF is reached, else loading has failed- return false
if(EOF == true)
{
fileLoaded = true;
fclose(file);
return true;
}
else return false;
}
和 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;
}
结构节点的定义:
//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 的错误:
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)
valgrind 使用 --leak-check=full、--leak-check=full 和 --show-leak-kinds=all 运行。我尝试从以前的帖子中引用类似的错误,但是上下文的差异使得我很难确定我应该做什么。第 84 行是读取 if(!(tempNode->children[index])) 的行。这似乎(在我看来)是问题的根本原因。
谢谢!
【问题讨论】:
-
您的调试器可能会告诉您更多信息
-
什么是结构节点? children 是指针数组吗?
-
minimal reproducible example 可能会有所帮助。
-
我已经添加了结构节点的定义。谢谢你的提问。 @Elan
标签: c memory-leaks