我正在使用哈佛大学的CS50 pset5,其中您的任务是将字典上传到您选择的数据结构中,然后拼写检查给定的文本。
我这次决定使用trie并正确检查拼写,没有内存泄漏。
但是,运行valgrind -v ./speller texts/lalaland.txt
似乎会从上下文返回9个错误。
鉴于没有内存泄漏,我似乎无法弄清楚究竟是什么问题。
==5897==
==5897== HEAP SUMMARY:
==5897== in use at exit: 0 bytes in 0 blocks
==5897== total heap usage: 367,084 allocs, 367,084 frees, 82,227,504 bytes allocated
==5897==
==5897== All heap blocks were freed -- no leaks are possible
==5897==
==5897== ERROR SUMMARY: 9913647 errors from 9 contexts (suppressed: 0 from 0)
==5897==
==5897== 1 errors in context 1 of 9:
==5897== Conditional jump or move depends on uninitialised value(s)
==5897== at 0x422434: unload_node (dictionary2.c:28)
==5897== by 0x42362C: unload (dictionary2.c:170)
==5897== by 0x421564: main (speller.c:152)
==5897== Uninitialised value was created by a heap allocation
==5897== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5897== by 0x422E91: load (dictionary2.c:104)
==5897== by 0x420992: main (speller.c:40)
==5897==
==5897==
==5897== 216 errors in context 2 of 9:
==5897== Conditional jump or move depends on uninitialised value(s)
==5897== at 0x422B80: check (dictionary2.c:73)
==5897== by 0x421363: main (speller.c:112)
==5897== Uninitialised value was created by a heap allocation
==5897== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5897== by 0x423216: load (dictionary2.c:131)
==5897== by 0x420992: main (speller.c:40)
==5897==
==5897==
==5897== 221 errors in context 3 of 9:
==5897== Conditional jump or move depends on uninitialised value(s)
==5897== at 0x422434: unload_node (dictionary2.c:28)
==5897== by 0x422534: unload_node (dictionary2.c:30)
==5897== by 0x42362C: unload (dictionary2.c:170)
==5897== by 0x421564: main (speller.c:152)
==5897== Uninitialised value was created by a heap allocation
==5897== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5897== by 0x423216: load (dictionary2.c:131)
==5897== by 0x420992: main (speller.c:40)
==5897==
==5897==
==5897== 739 errors in context 4 of 9:
==5897== Conditional jump or move depends on uninitialised value(s)
==5897== at 0x4213E7: main (speller.c:119)
==5897== Uninitialised value was created by a heap allocation
==5897== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5897== by 0x423216: load (dictionary2.c:131)
==5897== by 0x420992: main (speller.c:40)
==5897==
==5897==
==5897== 739 errors in context 5 of 9:
==5897== Conditional jump or move depends on uninitialised value(s)
==5897== at 0x4213C0: main (speller.c:119)
==5897== Uninitialised value was created by a heap allocation
==5897== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5897== by 0x423216: load (dictionary2.c:131)
==5897== by 0x420992: main (speller.c:40)
==5897==
==5897==
==5897== 739 errors in context 6 of 9:
==5897== Conditional jump or move depends on uninitialised value(s)
==5897== at 0x422DD5: check (dictionary2.c:83)
==5897== by 0x421363: main (speller.c:112)
==5897== Uninitialised value was created by a heap allocation
==5897== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5897== by 0x423216: load (dictionary2.c:131)
==5897== by 0x420992: main (speller.c:40)
==5897==
==5897==
==5897== 9185 errors in context 7 of 9:
==5897== Conditional jump or move depends on uninitialised value(s)
==5897== at 0x422434: unload_node (dictionary2.c:28)
==5897== by 0x422534: unload_node (dictionary2.c:30)
==5897== by 0x422534: unload_node (dictionary2.c:30)
==5897== by 0x42362C: unload (dictionary2.c:170)
==5897== by 0x421564: main (speller.c:152)
==5897== Uninitialised value was created by a heap allocation
==5897== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5897== by 0x423216: load (dictionary2.c:131)
==5897== by 0x420992: main (speller.c:40)
==5897==
==5897==
==5897== 367081 errors in context 8 of 9:
==5897== Conditional jump or move depends on uninitialised value(s)
==5897== at 0x423205: load (dictionary2.c:127)
==5897== by 0x420992: main (speller.c:40)
==5897== Uninitialised value was created by a heap allocation
==5897== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5897== by 0x422E91: load (dictionary2.c:104)
==5897== by 0x420992: main (speller.c:40)
==5897==
==5897==
==5897== 9534726 errors in context 9 of 9:
==5897== Conditional jump or move depends on uninitialised value(s)
==5897== at 0x422434: unload_node (dictionary2.c:28)
==5897== by 0x422534: unload_node (dictionary2.c:30)
==5897== by 0x422534: unload_node (dictionary2.c:30)
==5897== by 0x422534: unload_node (dictionary2.c:30)
==5897== by 0x42362C: unload (dictionary2.c:170)
==5897== by 0x421564: main (speller.c:152)
==5897== Uninitialised value was created by a heap allocation
==5897== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5897== by 0x423216: load (dictionary2.c:131)
==5897== by 0x420992: main (speller.c:40)
==5897==
==5897== ERROR SUMMARY: 9913647 errors from 9 contexts (suppressed: 0 from 0)
dictionary2.c:
// Implements a dictionary's functionality
#include "dictionary.h"
// Define node to be used in hashtable
typedef struct node
{
bool is_word;
struct node *children[27];
}
node;
// Define root
node *root;
// Global variable to track word count
unsigned int word_count = 0;
// Global boolean to track whether dictionary was loaded or not
bool loaded = false;
// Helper function to unload trie nodes
void unload_node(node *firstnode)
{
for (int i = 0; i < 27; i++)
{
if (firstnode->children[i] != NULL) // line 28
{
unload_node(firstnode->children[i]); // line 30
}
}
free(firstnode);
return;
}
// Returns true if word is in dictionary else false
bool check(const char *word)
{
// TODO
// Copy the word as word only has read access
int length = strlen(word);
char word_copy[length + 1];
// Lowercase the word
for (int i = 0; i < length; i++)
{
word_copy[i] = tolower(word[i]);
}
// Nul terminate the string
word_copy[length] = '\0';
// Direct traversal pointer to root
node *trav = root;
for (int i = 0, n = strlen(word_copy); i < n; i++)
{
// Find numerical value of letter
int alphanum;
if (word_copy[i] == 39)
{
// If it is apostrophe, allocate last slot in array
alphanum = 26;
}
else
{
alphanum = word_copy[i] - 97;
}
if (trav->children[alphanum] != NULL) // line 73
{
trav = trav->children[alphanum];
}
else
{
return false;
}
}
return trav->is_word; // line 83
}
// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
// TODO
// Open dictionary file
FILE *inptr = fopen(dictionary, "r");
if (inptr == NULL)
{
fclose(inptr);
fprintf(stderr, "Could not open %s.\n", dictionary);
return 2;
}
// Scan through every word in dictionary and store into new node
char wordBuffer[LENGTH + 1];
// Malloc root node
root = (node*) malloc(sizeof(node)); // line 104
while (fscanf(inptr, "%s", wordBuffer) != EOF)
{
// Create traversal pointer to the root
node *trav = root;
for (int i = 0, n = strlen(wordBuffer); i < n; i++)
{
// Find numeric value of letter
int alphanum;
if (wordBuffer[i] == 39)
{
// If it is apostrophe, allocate last space in children's array
alphanum = 26;
}
else
{
alphanum = wordBuffer[i] - 97;
}
if (trav->children[alphanum] == NULL) // line 127
{
// If node does not exist in array slot, allocate memory for new node
trav->children[alphanum] = malloc(sizeof(node)); // line 131
}
// Redirect trav to child
trav = trav->children[alphanum];
}
trav->is_word = true;
word_count++;
}
fclose(inptr);
loaded = true;
return true;
}
// Returns number of words in dictionary if loaded else 0 if not yet loaded
unsigned int size(void)
{
// TODO
if (loaded)
{
return word_count;
}
else
{
return 0;
}
}
// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
// TODO
node *trav = root;
unload_node(trav); // line 170
return true;
}
任何帮助都非常感谢:)
答案 0 :(得分:0)
让我们看一下9的上下文8:
==5897== 367081 errors in context 8 of 9:
==5897== Conditional jump or move depends on uninitialised value(s)
==5897== at 0x423205: load (dictionary2.c:127)
==5897== by 0x420992: main (speller.c:40)
==5897== Uninitialised value was created by a heap allocation
==5897== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5897== by 0x422E91: load (dictionary2.c:104)
==5897== by 0x420992: main (speller.c:40)
==5897==
条件跳转或移动取决于未初始化的值
这意味着您在没有初始化if (something)
的情况下执行something
。它在第127行:
if (trav->children[alphanum] == NULL)
未初始化的值必须为trav->children[alphanum]
。通过你的循环查看,你看到你有
root = (node*) malloc(sizeof(node)); // line 104
...
node *trav = root;
你malloced root
但在尝试分支之前从未实际设置过任何值。在使用之前,您应该清空root->children
中的条目。
您还可以通过查看错误的后半部分来看到这一点:
未初始化的值是由堆分配
创建的
它指向第104行,告诉您第104行的分配创建了未初始化的值,从而得出相同的结论。
答案 1 :(得分:0)
要添加到@fennel的答案,我的load
函数在遇到单词的最后一个字母时似乎有问题,因为它创建一个新节点只是为了通过{表示单词的结尾{1}}。该节点的is_word = true
数组也未初始化,这是我的错误来源。
children
一个简单的解决方法是while (fscanf(inptr, "%s", wordBuffer) != EOF)
{
// Create traversal pointer to the root
node *trav = root;
for (int i = 0, n = strlen(wordBuffer); i < n; i++)
{
// Find numeric value of letter
int alphanum;
if (wordBuffer[i] == 39)
{
// If it is apostrophe, allocate last space in children's array
alphanum = 26;
}
else
{
alphanum = wordBuffer[i] - 97;
}
if (trav->children[alphanum] == NULL) // line 127
{
// If node does not exist in array slot, allocate memory for new node
trav->children[alphanum] = malloc(1, sizeof(node)); // line 131
}
// Redirect trav to child
trav = trav->children[alphanum];
}
trav->is_word = true;
word_count++;
}
而不是calloc
,因为:
malloc