CS50 pset5 Speller [2021] - “:( 程序没有内存错误”
CS50 pset5 Speller [2021] - " :( program is free of memory errors"
我收到错误“:( 程序没有内存错误 valgrind 测试失败;有关详细信息,请参阅日志。”
这是我的代码:
// Implements a dictionary's functionality
#include <stdbool.h>
#include <stdio.h>
#include "dictionary.h"
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
// Represents a node in a hash table
typedef struct node
{
char word[LENGTH + 1];
struct node *next;
}
node;
// Number of buckets in hash table
const unsigned int N = 27;
// Hash table
node *table[N];
int size_n = 0;
```// Returns true if word is in dictionary, else false
bool check(const char *word)
{
//Hash Number
unsigned int number;
number = hash(word);
node *n;
n = table[number];
//Check for the word in the linked-list inside the Hash table
while (n->next != NULL)
{
if (strcasecmp(n->word, word) == 0)
{
return true;
}
n = n->next;
}
//Return false if word not found in Hash table
return false;
}
// Hashes word to a number
unsigned int hash(const char *word)
{
unsigned int number = 0;
//If word starts with '
if (word[0] == 44)
{
number = 0;
}
//Assign Hash number alphbetically
else if (toupper(word[0]) >=65 && toupper(word[0])<=90)
{
number = (toupper(word[0]) - 64);
}
return number;
}
// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
//Open dictionary
FILE *F = fopen(dictionary, "r");
//Check if file is opened
if (F == NULL)
{
return false;
}
//Temporary string to store words
char temp[LENGTH + 1];
unsigned int number;
//Initialize linked-list pointers to NULL so that last element of every linked-list points to NULL
node *p = malloc(sizeof(node));
for (int i = 0; i < N; i++)
{
p->next = NULL;
table[i] = p;
}
//Loads the dictionary in the Hash Table
while(fscanf(F, "%s", temp) != EOF)
{
printf("%s", temp);
number = hash(temp);
//Allocate memory for the dictionary word
node *n = malloc(sizeof(node));
if (n == NULL)
{
return false;
}
//Store dictionary word in the node
strcpy(n->word, temp);
//Insert the node between head and first element of linked-list
n->next = table[number];
table[number] = n;
//Counts the number of words of the dictionary stored in the memory
size_n++;
}
free(p);
fclose(F);
return true;
}
// Returns number of words in dictionary if loaded, else 0 if not yet loaded
unsigned int size(void)
{
return size_n;
}
// Unloads dictionary from memory, returning true if successful, else false
bool unload(void)
{
//Iterates over each head of the Hash table
for (int i = 0; i < N; i++)
{
node *temp = NULL;
node *dlt = NULL;
temp = table[i];
while (temp->next != NULL)
{
dlt = temp;
temp = temp->next;
free(dlt);
}
}
return true;
}
以下是 valgrind check50 中的错误:
原因
valgrind 测试失败;有关详细信息,请参阅日志。
日志
running valgrind --show-leak-kinds=all --xml=yes --xml-file=/tmp/tmplj9r16i7 -- ./speller substring/dict substring/text...
checking for output "MISSPELLED WORDS\n\nca\ncats\ncaterpill\ncaterpillars\n\nWORDS MISSPELLED: 4\nWORDS IN DICTIONARY: 2\nWORDS IN TEXT: 6\n"...
checking that program exited with status 0...
checking for valgrind errors...
Invalid read of size 8: (file: dictionary.c, line: 40)
Invalid read of size 8: (file: dictionary.c, line: 149)
我找不到其他方法来解决这个问题。如果我这样做,我会出错。
valgrind 错误对我来说并不明显。我做错了什么?
这是错误的
//Initialize linked-list pointers to NULL so that last element of every linked-list points to NULL
node *p = malloc(sizeof(node));
for (int i = 0; i < N; i++)
{
p->next = NULL;
table[i] = p;
}
您没有将链表指针初始化为 NULL,而是将它们初始化为 p
,然后在加载结束时在 p 上调用 free。这会使每个链表处于无效状态,因为头指针指向您不再拥有的内存。
table[i] = NULL;
本来是正确的,但仍然没有必要,因为 table 是一个全局变量,因此默认初始化为零。
检查的这部分也是不正确的,已经指出了。
while (n->next != NULL)
检查next是否为NULL总是错误的。我们不关心 next 是否为 NULL,我们只关心 n 是否为 NULL。
我收到错误“:( 程序没有内存错误 valgrind 测试失败;有关详细信息,请参阅日志。”
这是我的代码:
// Implements a dictionary's functionality
#include <stdbool.h>
#include <stdio.h>
#include "dictionary.h"
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
// Represents a node in a hash table
typedef struct node
{
char word[LENGTH + 1];
struct node *next;
}
node;
// Number of buckets in hash table
const unsigned int N = 27;
// Hash table
node *table[N];
int size_n = 0;
```// Returns true if word is in dictionary, else false
bool check(const char *word)
{
//Hash Number
unsigned int number;
number = hash(word);
node *n;
n = table[number];
//Check for the word in the linked-list inside the Hash table
while (n->next != NULL)
{
if (strcasecmp(n->word, word) == 0)
{
return true;
}
n = n->next;
}
//Return false if word not found in Hash table
return false;
}
// Hashes word to a number
unsigned int hash(const char *word)
{
unsigned int number = 0;
//If word starts with '
if (word[0] == 44)
{
number = 0;
}
//Assign Hash number alphbetically
else if (toupper(word[0]) >=65 && toupper(word[0])<=90)
{
number = (toupper(word[0]) - 64);
}
return number;
}
// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
//Open dictionary
FILE *F = fopen(dictionary, "r");
//Check if file is opened
if (F == NULL)
{
return false;
}
//Temporary string to store words
char temp[LENGTH + 1];
unsigned int number;
//Initialize linked-list pointers to NULL so that last element of every linked-list points to NULL
node *p = malloc(sizeof(node));
for (int i = 0; i < N; i++)
{
p->next = NULL;
table[i] = p;
}
//Loads the dictionary in the Hash Table
while(fscanf(F, "%s", temp) != EOF)
{
printf("%s", temp);
number = hash(temp);
//Allocate memory for the dictionary word
node *n = malloc(sizeof(node));
if (n == NULL)
{
return false;
}
//Store dictionary word in the node
strcpy(n->word, temp);
//Insert the node between head and first element of linked-list
n->next = table[number];
table[number] = n;
//Counts the number of words of the dictionary stored in the memory
size_n++;
}
free(p);
fclose(F);
return true;
}
// Returns number of words in dictionary if loaded, else 0 if not yet loaded
unsigned int size(void)
{
return size_n;
}
// Unloads dictionary from memory, returning true if successful, else false
bool unload(void)
{
//Iterates over each head of the Hash table
for (int i = 0; i < N; i++)
{
node *temp = NULL;
node *dlt = NULL;
temp = table[i];
while (temp->next != NULL)
{
dlt = temp;
temp = temp->next;
free(dlt);
}
}
return true;
}
以下是 valgrind check50 中的错误:
原因 valgrind 测试失败;有关详细信息,请参阅日志。 日志
running valgrind --show-leak-kinds=all --xml=yes --xml-file=/tmp/tmplj9r16i7 -- ./speller substring/dict substring/text...
checking for output "MISSPELLED WORDS\n\nca\ncats\ncaterpill\ncaterpillars\n\nWORDS MISSPELLED: 4\nWORDS IN DICTIONARY: 2\nWORDS IN TEXT: 6\n"...
checking that program exited with status 0...
checking for valgrind errors...
Invalid read of size 8: (file: dictionary.c, line: 40)
Invalid read of size 8: (file: dictionary.c, line: 149)
我找不到其他方法来解决这个问题。如果我这样做,我会出错。
valgrind 错误对我来说并不明显。我做错了什么?
这是错误的
//Initialize linked-list pointers to NULL so that last element of every linked-list points to NULL node *p = malloc(sizeof(node)); for (int i = 0; i < N; i++) { p->next = NULL; table[i] = p; }
您没有将链表指针初始化为 NULL,而是将它们初始化为 p
,然后在加载结束时在 p 上调用 free。这会使每个链表处于无效状态,因为头指针指向您不再拥有的内存。
table[i] = NULL;
本来是正确的,但仍然没有必要,因为 table 是一个全局变量,因此默认初始化为零。
检查的这部分也是不正确的,已经指出了。
while (n->next != NULL)
检查next是否为NULL总是错误的。我们不关心 next 是否为 NULL,我们只关心 n 是否为 NULL。