pset5 Speller - я не знаю, что не так с кодом. Может ли кто-нибудь помочь мне найти мою ошибку? Я включил все - PullRequest
0 голосов
/ 21 июня 2020

Я застрял примерно на 2-3 недели. Думаю, мне нужна помощь. Вот мой код

// Implements a dictionary's functionality

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <ctype.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 = 2600;

// Hash table
node *table[N];

// Counter for size
int counter;

// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
    // Making a pointer to the file which contains the dictionary
    FILE *file = fopen(dictionary, "r");
    // Declaring a temporary word to store the copied word from the dictionary
    char w[LENGTH + 1];
    // Check if memory is available
    if (file == NULL)
        return false;

    // Clearing the table to NULL
    for (int i = 0; i < N; i++)
    {
        table[i] = NULL;
    }

    // It will run until the file is finished
    while(fscanf(file, "%s", w) != EOF)
    {
        node *n = malloc(sizeof(node));
        // Check if memory is available
        if (n == NULL)
            return false;

        // Copy the word from the dictionary to w
        strcpy(n -> word, w);
        // Store the index at which the word should be stored
        int pos = hash(n -> word);

        // Set the 'next' value of 'n' to point at the head of the list
        n -> next = table[pos];
        table[pos] = n;

        // Increase the counter per word copied from the dictionary
        counter++;
        // Free the allocated memory
        free(n);
    }
    size();
    // close the file
    fclose(file);
    return true;
}

// Hashes word to a number
unsigned int hash(const char *word)
{
    // Idea inspired from "https://www.youtube.com/watch?v=2Ti5yvumFTU&t=782s"
    int sum = 0;
    for (int i = 0, len = strlen(word); i < len; i++)
    {
        sum +=  (int) word[i];
    }
    return (sum % N);
}

// Returns number of words in dictionary if loaded else 0 if not yet loaded
unsigned int size(void)
{
    return counter;
}

// Returns true if word is in dictionary else false
bool check(const char *word)
{
    // Make a temporary string to store the word to be checked
    char *temp = malloc(sizeof(char) * (LENGTH + 1));
    for (int i = 0; i < LENGTH; i++)
    {
        temp[i] = tolower(word[i]);
    }
    // Getting the hash value of the word to be searched
    int h = hash(temp);
    node *ptr = malloc(sizeof(node));
    temp[LENGTH] = '\0';

    // ptr searches table where the word would be if it exists
    ptr = table[h];
    while (ptr != NULL)
    {
        if (strcasecmp(temp, ptr -> word) == 0)
        {
            return true;
        }
        ptr = ptr -> next;
    }
    return false;
}

// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
    for (int i = 0; i < N; i++)
    {
        node *ptr = table[i];
        // Free each linked list
        while (ptr != NULL)
        {
            node *tmp = ptr;;
            ptr = ptr->next;
            free(tmp);
        }
    }
    return true;
}

Вот сообщение help50 valgrind

==9041== Memcheck, a memory error detector
==9041== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==9041== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==9041== Command: ./speller texts/cat.txt
==9041== 

MISSPELLED WORDS

A
==9041== Invalid read of size 1
==9041==    at 0x4C3361E: strcasecmp (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9041==    by 0x401294: check (dictionary.c:111)
==9041==    by 0x400C89: main (speller.c:112)
==9041==  Address 0x63233c0 is 0 bytes inside a block of size 56 free'd
==9041==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9041==    by 0x401162: load (dictionary.c:70)
==9041==    by 0x400964: main (speller.c:40)
==9041==  Block was alloc'd at
==9041==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9041==    by 0x4010EC: load (dictionary.c:51)
==9041==    by 0x400964: main (speller.c:40)
==9041== 
==9041== Invalid read of size 8
==9041==    at 0x4012BD: check (dictionary.c:117)
==9041==    by 0x400C89: main (speller.c:112)
==9041==  Address 0x63233f0 is 48 bytes inside a block of size 56 free'd
==9041==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9041==    by 0x401162: load (dictionary.c:70)
==9041==    by 0x400964: main (speller.c:40)
==9041==  Block was alloc'd at
==9041==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9041==    by 0x4010EC: load (dictionary.c:51)
==9041==    by 0x400964: main (speller.c:40)
==9041== 
==9041== Invalid free() / delete / delete[] / realloc()
==9041==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9041==    by 0x4012AF: check (dictionary.c:114)
==9041==    by 0x400C89: main (speller.c:112)
==9041==  Address 0x5816670 is 0 bytes inside a block of size 56 free'd
==9041==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9041==    by 0x401162: load (dictionary.c:70)
==9041==    by 0x400964: main (speller.c:40)
==9041==  Block was alloc'd at
==9041==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9041==    by 0x4010EC: load (dictionary.c:51)
==9041==    by 0x400964: main (speller.c:40)
==9041== 
==9041== Invalid read of size 8
==9041==    at 0x401333: unload (dictionary.c:134)
==9041==    by 0x400E09: main (speller.c:152)
==9041==  Address 0x55cc320 is 48 bytes inside a block of size 56 free'd
==9041==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9041==    by 0x401162: load (dictionary.c:70)
==9041==    by 0x400964: main (speller.c:40)
==9041==  Block was alloc'd at
==9041==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9041==    by 0x4010EC: load (dictionary.c:51)
==9041==    by 0x400964: main (speller.c:40)
==9041== 
==9041== Invalid free() / delete / delete[] / realloc()
==9041==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9041==    by 0x401346: unload (dictionary.c:135)
==9041==    by 0x400E09: main (speller.c:152)
==9041==  Address 0x55cc2f0 is 0 bytes inside a block of size 56 free'd
==9041==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9041==    by 0x401162: load (dictionary.c:70)
==9041==    by 0x400964: main (speller.c:40)
==9041==  Block was alloc'd at
==9041==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9041==    by 0x4010EC: load (dictionary.c:51)
==9041==    by 0x400964: main (speller.c:40)
==9041== 

WORDS MISSPELLED:     1
WORDS IN DICTIONARY:  143091
WORDS IN TEXT:        6
TIME IN load:         1.57
TIME IN check:        0.00
TIME IN size:         0.00
TIME IN unload:       0.16
TIME IN TOTAL:        1.74

==9041== 
==9041== HEAP SUMMARY:
==9041==     in use at exit: 336 bytes in 6 blocks
==9041==   total heap usage: 143,108 allocs, 286,198 frees, 8,024,028 bytes allocated
==9041== 
==9041== 336 bytes in 6 blocks are definitely lost in loss record 1 of 1
==9041==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9041==    by 0x401260: check (dictionary.c:104)
==9041==    by 0x400C89: main (speller.c:112)
==9041== 
==9041== LEAK SUMMARY:
==9041==    definitely lost: 336 bytes in 6 blocks
==9041==    indirectly lost: 0 bytes in 0 blocks
==9041==      possibly lost: 0 bytes in 0 blocks
==9041==    still reachable: 0 bytes in 0 blocks
==9041==         suppressed: 0 bytes in 0 blocks
==9041== 
==9041== For counts of detected and suppressed errors, rerun with: -v
==9041== ERROR SUMMARY: 286630 errors from 6 contexts (suppressed: 0 from 0)

Asking for help...

==9041== 336 bytes in 6 blocks are definitely lost in loss record 1 of 1
==9041==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9041==    by 0x401260: check (dictionary.c:104)
==9041==    by 0x400C89: main (speller.c:112)

Looks like your program leaked 336 bytes of memory. Did you forget to free memory that you allocated via malloc? Take a closer look at line 104 of dictionary.c.

И сообщение check50

: ) dictionary. c, dictionary.h и Makefile существуют :) спеллер компилирует :( обрабатывает большинство базовых c слов, правильно ожидаемых "НЕПРАВИЛЬНАЯ РАБОТА ...", а не "НЕПРАВИЛЬНАЯ РАБОТА ..." :) обрабатывает слова минимальной длины (1 символ) :) обрабатывает слова максимальной длины (45 символов) :) правильно обрабатывает слова с апострофами :( проверка орфографии выполняется без учета регистра ожидаемого "ПРОПУСТИТЕ РАБОТУ ...", а не "ПРОПУСТИТЕ РАБОТУ ..." :( обрабатывает подстроки должным образом ожидаемые "НЕПРАВИЛЬНАЯ РАБОТА ...", а не "НЕПРАВИЛЬНАЯ РАБОТА ..." : | программа свободна от ошибок памяти не может проверить, пока хмурый взгляд не перевернется

1 Ответ

0 голосов
/ 21 июня 2020

Valgrind не сообщил истинную причину. Код проблемы c:

    while(fscanf(file, "%s", w) != EOF)
    {
        node *n = malloc(sizeof(node));
        
        // Free the allocated memory
        free(n);  
    }

Вы должны только free их в функции unload.

...