我做错了什么?
没有内存泄漏,但是valgrind仍然抱怨,我没有弄清楚是什么导致了这个错误。
我很高兴有人能帮助我弄清楚我在这里做错了什么。
/****************************************************************************
* dictionary.c
*
* Computer Science 50
* Problem Set 5
*
* Implements a dictionary's functionality.
***************************************************************************/
#include <stdbool.h>
#include "dictionary.h"
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
struct dict {
struct dict *next;
char *word;
};
#define HASHSIZE 26
static struct dict *hashtab[HASHSIZE];
unsigned hash(const char *key)
{
unsigned index = toupper(key[0]) - 'A';
return index % HASHSIZE;
}
struct dict *lookup(const char *s)
{
struct dict *np;
for (np = hashtab[hash(s)]; np != NULL; np = np->next) {
if (strcmp(s, np->word) == 0) {
return np; /* found */
}
}
return NULL; /* not found*/
}
/**
* Returns true if word is in dictionary else false.
*/
bool check(const char* word)
{
if (lookup(word) != NULL) {
return true;
}
else {
int i;
for (i = 0; word[i] != '\0' && !isupper(word[i]); ++i)
;
if (word[i] != '\0') {
char newword[LENGTH + 1];
for (i = 0; word[i] != '\0'; ++i) {
newword[i] = tolower(word[i]);
}
newword[i] = '\0';
if (lookup(newword) != NULL) {
return true;
}
}
}
return false;
}
int getword(FILE *fp, char **s)
{
int c, i;
char word[LENGTH + 1];
i = 0;
while ((c = fgetc(fp)) != '\n' && c != EOF && i < LENGTH + 1) {
word[i++] = c;
}
word[i] = '\0';
if (c == EOF) {
return EOF;
}
if ((*s = malloc(i)) == NULL) {
return EOF;
}
strncpy(*s, word, i);
return i;
}
static unsigned nofwords;
struct dict *install(char *word)
{
struct dict *np;
unsigned hashval;
if ((np = lookup(word)) == NULL) { /* Not found */
np = malloc(sizeof(*np));
if (np == NULL) {
return NULL;
}
struct dict *hpt;
hashval = hash(word);
if (hashtab[hashval] != NULL) {
for (hpt = hashtab[hashval]; hpt->next != NULL; hpt = hpt->next)
;
hpt->next = np;
}
else {
np->next = hashtab[hashval];
hashtab[hashval] = np;
}
np->word = word;
}
else {
free(word);
}
++nofwords;
return np;
}
/**
* Loads dictionary into memory. Returns true if successful else false.
*/
bool load(const char* dictionary)
{
FILE *fp;
if ((fp = fopen(dictionary,"r")) == NULL) {
return false;
}
char *s = NULL;
while (getword(fp, &s) != EOF) {
if (install(s) == NULL) {
fclose(fp);
return false;
}
}
fclose(fp);
return true;
}
/**
* Returns number of words in dictionary if loaded else 0 if not yet loaded.
*/
unsigned int size(void)
{
return nofwords;
}
/**
* Unloads dictionary from memory. Returns true if successful else false.
*/
bool unload(void)
{
int i;
struct dict *np;
struct dict *tmp;
for (i = 0; i < HASHSIZE; i++) {
if (hashtab[i] != NULL) {
np = hashtab[i];
while (np != NULL) {
free(np->word);
tmp = np;
np = np->next;
free(tmp);
}
}
}
return true;
}
Valgrind输出
jharvard@appliance (~/Dropbox/pset5): valgrind ./speller ~cs50/pset5/dictionaries/small text
==18743== Memcheck, a memory error detector
==18743== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==18743== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==18743== Command: ./speller /home/cs50/pset5/dictionaries/small text
==18743==
==18743== Invalid read of size 1
==18743== at 0x402E5CA: strcmp (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==18743== by 0x8049012: lookup (dictionary.c:39)
==18743== by 0x8049296: install (dictionary.c:102)
==18743== by 0x80493F6: load (dictionary.c:139)
==18743== by 0x8048785: main (speller.c:45)
==18743== Address 0x41f51bb is 0 bytes after a block of size 3 alloc'd
==18743== at 0x402A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==18743== by 0x804922D: getword (dictionary.c:85)
==18743== by 0x80493E0: load (dictionary.c:138)
==18743== by 0x8048785: main (speller.c:45)
==18743==
MISSPELLED WORDS
==18743== Conditional jump or move depends on uninitialised value(s)
==18743== at 0x8048FF8: lookup (dictionary.c:38)
==18743== by 0x8049066: check (dictionary.c:51)
==18743== by 0x8048B1D: main (speller.c:117)
==18743==
==18743== Invalid read of size 1
==18743== at 0x402E5CA: strcmp (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==18743== by 0x8049012: lookup (dictionary.c:39)
==18743== by 0x8049145: check (dictionary.c:64)
==18743== by 0x8048B1D: main (speller.c:117)
==18743== Address 0x41f51bb is 0 bytes after a block of size 3 alloc'd
==18743== at 0x402A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==18743== by 0x804922D: getword (dictionary.c:85)
==18743== by 0x80493E0: load (dictionary.c:138)
==18743== by 0x8048785: main (speller.c:45)
==18743==
==18743== Conditional jump or move depends on uninitialised value(s)
==18743== at 0x8049492: unload (dictionary.c:168)
==18743== by 0x8048D14: main (speller.c:157)
==18743==
WORDS MISSPELLED: 0
WORDS IN DICTIONARY: 2
WORDS IN TEXT: 1
TIME IN load: 0.07
TIME IN check: 0.01
TIME IN size: 0.00
TIME IN unload: 0.01
TIME IN TOTAL: 0.08
==18743==
==18743== HEAP SUMMARY:
==18743== in use at exit: 0 bytes in 0 blocks
==18743== total heap usage: 6 allocs, 6 frees, 734 bytes allocated
==18743==
==18743== All heap blocks were freed -- no leaks are possible
==18743==
==18743== For counts of detected and suppressed errors, rerun with: -v
==18743== Use --track-origins=yes to see where uninitialised values come from
==18743== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 0 from 0)
答案 0 :(得分:1)
条件跳转或移动取决于未初始化的值
static struct dict *hashtab[HASHSIZE] = {0};
在大小为3的块之后0个字节
getword() -> *s = malloc(i);
- &GT;&GT;这里我可能是零,因此,0大小的malloc(考虑文件有空行而不是有效单词的情况)
读取大小为1(strcmp)无效
lookup() -> if (strcmp(s, np->word) == 0)
这里,s可能是空字符串,所以添加空字符串处理(不是为空字符串调用strcmp(),返回错误)会有所帮助。
此外,您的getword()函数需要进行以下修改:
while ((c = fgetc(fp)) != '\n' && c != EOF && i < LENGTH + 1)
---&GT;变化是i&lt; LENGTH而不是i&lt;长度+ 1 (我从0开始,所以它可以一直到LENGTH-1以允许在索引LENGTH结束时容纳'\ 0'。
if ((*s = malloc(i)) == NULL)
---&GT; malloc应该是i + 1长度以容纳'\ 0'。
strncpy(*s, word, i);
---&GT;添加代码将'\ 0'放在s的末尾,即(* s)[i] ='\ 0';在strncpy()之后调用。
答案 1 :(得分:0)
Invalid read of size 1
Valgrind告诉你,你尝试读取1个字节(在strcmp中),你不允许阅读。
可能是因为没有函数定义您尝试与s
进行比较的字符串np->word
(第39行)。
Conditional jump or move depends on uninitialised value(s)
这意味着您正在尝试在条件中使用单位变量。
尝试在调试器中运行代码并按照字符串的值来查看它们在将它们作为函数的参数提供时是否指向某些内容。