CS50 speller pset 5(访问了不属于我的1个字节但找不到字节)
CS50 speller pset 5 (accessed 1 byte that does not belong to me but can't find the byte)
在 运行 我的代码通过 help50 Valgrind 后,我收到以下错误消息:
==6830== Invalid read of size 1
==6830== at 0x4C33614: strcasecmp (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6830== by 0x401176: check (dictionary.c:52)
==6830== by 0x400CD9: main (speller.c:112)
看起来您正在尝试访问不属于您的 1 字节内存?您是否尝试索引超出其范围的数组?仔细查看 dictionary.c.
的第 52 行
我认为这与我的检查功能有关,但第 52 行只是一个 if 语句,我不知道我试图从哪里访问那 1 个字节。**
我的代码如下:
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <strings.h>
#include "dictionary.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 = 1000;
//Number of words
unsigned int noWords = 0;
//Variable to check if dictionary loaded
bool isLoaded = false;
// Hash table
node *table[N];
// Returns true if word is in dictionary else false
bool check(const char *word)
{
//Changing letters to lower case because case insensitive
//Copy created because word argument is a constant. copy can be edited
int n = strlen(word) + 1;
char copy[LENGTH + 1];
for (int i = 0; i < n; i++)
{
copy[i] = tolower(word[i]);
}
// Add null terminator to end string
copy[n] = '[=10=]';
//Hash the word to convert it to index and check if it's in any of the linked lists
int index = hash(copy);
if (table[index] != NULL) //Check if word is in linked list
{
for (node *cursor = table[index]; cursor != NULL; cursor = cursor -> next)
{
if (strcasecmp(cursor -> word, copy) == 0)
{
return true;
}
}
}
return false;
}
// Hashes word to a number
unsigned int hash(const char *word)
{
//Taken from http://www.cse.yorku.ca/~oz/hash.html (by djb2)
unsigned long h = 5381;
int c;
while ((c = *word++))
{
c = tolower(c);
h = (((h << 5) + h) + c) % N; /* hash * 33 + c*/
}
return h;
}
// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
char word[LENGTH + 1];
//Open dictionary
FILE *f = fopen(dictionary, "r");
//Check if file can be opened
if (f == NULL)
{
printf("%s\n", "File cannot be opened!");
return false;
}
//Read strings from file
while (fscanf(f, "%s", word) != EOF)
{
noWords++;
node *newNodePointer = malloc(sizeof(node));
if (newNodePointer == NULL)
{
unload();
printf("Out of memory");
return false;
}
int index = hash(word);//hashtable is an array of linked list. index helps insert node into hashtable
strcpy(newNodePointer -> word, word);//Copies word from infile into new node's word field
if (table[index] == NULL)//Check if same word already exists in the bucket
{
newNodePointer -> next = NULL;
table[index] = newNodePointer;
}
else
{
newNodePointer -> next = table[index];
table[index] = newNodePointer;
}
free(newNodePointer);
}
fclose(f);
isLoaded = true;
return true;
}
// Returns number of words in dictionary if loaded else 0 if not yet loaded
unsigned int size(void)
{
if (isLoaded)
{
return noWords;
}
return 0;
}
// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
//Check if there's even a loaded dictionary
if (!isLoaded)
{
return false;
}
//Iterate through hashtable
for (int i = 0; i < N; i++)
{
if (table[i] != NULL)
{
node *cursor = table[i];
while (cursor != NULL)
{
node *tmp = table[i]; //tmp pointer continues pointing at table[i] while cursor points at next item in hashtable
cursor = cursor -> next;
free(tmp);
}
}
}
return true;
}
问题出在加载中:free(newNodePointer);
。它只是释放了存储单词和下一个指针的内存!
在 运行 我的代码通过 help50 Valgrind 后,我收到以下错误消息:
==6830== Invalid read of size 1 ==6830== at 0x4C33614: strcasecmp (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==6830== by 0x401176: check (dictionary.c:52) ==6830== by 0x400CD9: main (speller.c:112)
看起来您正在尝试访问不属于您的 1 字节内存?您是否尝试索引超出其范围的数组?仔细查看 dictionary.c.
的第 52 行我认为这与我的检查功能有关,但第 52 行只是一个 if 语句,我不知道我试图从哪里访问那 1 个字节。**
我的代码如下:
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <strings.h>
#include "dictionary.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 = 1000;
//Number of words
unsigned int noWords = 0;
//Variable to check if dictionary loaded
bool isLoaded = false;
// Hash table
node *table[N];
// Returns true if word is in dictionary else false
bool check(const char *word)
{
//Changing letters to lower case because case insensitive
//Copy created because word argument is a constant. copy can be edited
int n = strlen(word) + 1;
char copy[LENGTH + 1];
for (int i = 0; i < n; i++)
{
copy[i] = tolower(word[i]);
}
// Add null terminator to end string
copy[n] = '[=10=]';
//Hash the word to convert it to index and check if it's in any of the linked lists
int index = hash(copy);
if (table[index] != NULL) //Check if word is in linked list
{
for (node *cursor = table[index]; cursor != NULL; cursor = cursor -> next)
{
if (strcasecmp(cursor -> word, copy) == 0)
{
return true;
}
}
}
return false;
}
// Hashes word to a number
unsigned int hash(const char *word)
{
//Taken from http://www.cse.yorku.ca/~oz/hash.html (by djb2)
unsigned long h = 5381;
int c;
while ((c = *word++))
{
c = tolower(c);
h = (((h << 5) + h) + c) % N; /* hash * 33 + c*/
}
return h;
}
// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
char word[LENGTH + 1];
//Open dictionary
FILE *f = fopen(dictionary, "r");
//Check if file can be opened
if (f == NULL)
{
printf("%s\n", "File cannot be opened!");
return false;
}
//Read strings from file
while (fscanf(f, "%s", word) != EOF)
{
noWords++;
node *newNodePointer = malloc(sizeof(node));
if (newNodePointer == NULL)
{
unload();
printf("Out of memory");
return false;
}
int index = hash(word);//hashtable is an array of linked list. index helps insert node into hashtable
strcpy(newNodePointer -> word, word);//Copies word from infile into new node's word field
if (table[index] == NULL)//Check if same word already exists in the bucket
{
newNodePointer -> next = NULL;
table[index] = newNodePointer;
}
else
{
newNodePointer -> next = table[index];
table[index] = newNodePointer;
}
free(newNodePointer);
}
fclose(f);
isLoaded = true;
return true;
}
// Returns number of words in dictionary if loaded else 0 if not yet loaded
unsigned int size(void)
{
if (isLoaded)
{
return noWords;
}
return 0;
}
// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
//Check if there's even a loaded dictionary
if (!isLoaded)
{
return false;
}
//Iterate through hashtable
for (int i = 0; i < N; i++)
{
if (table[i] != NULL)
{
node *cursor = table[i];
while (cursor != NULL)
{
node *tmp = table[i]; //tmp pointer continues pointing at table[i] while cursor points at next item in hashtable
cursor = cursor -> next;
free(tmp);
}
}
}
return true;
}
问题出在加载中:free(newNodePointer);
。它只是释放了存储单词和下一个指针的内存!