pset5 Speller 中的内存错误,表示我正在尝试访问我无权访问的 8 字节内存

问题描述 投票:0回答:1

我根据问题集 5 制作了拼写器程序,除了一些我无法解决的内存错误之外,它一切正常。我的代码如下:

// Implements a dictionary's functionality

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

// TODO: Choose number of buckets in hash table
const unsigned int N = 26;

int words = 0;

// Hash table
node *table[N];

// Returns true if word is in dictionary, else false
bool check(const char *word)
{
    // TODO
    node *ptr = table[hash(word)];
    while (ptr != NULL)
    {
        if (strcasecmp(word, ptr->word) == 0)
        {
            return true;
        }
            ptr = ptr->next;
    }
    return false;
}

// Hashes word to a number
unsigned int hash(const char *word)
{
    // TODO: Improve this hash function
    return toupper(word[0]) - 'A';
}

// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
    // Open the dictionary file
    FILE *source = fopen(dictionary, "r");
    if(source == NULL)
    {
        return false;
    }
    char *buffer = malloc(LENGTH + 1);
    if (buffer == NULL)
    {
        return false;
    }

    // Read each word in the file
    while(fscanf(source, "%s", buffer) != EOF)
    {
        // Add each word to the hash table
        node *ptr = table[hash(buffer)];
        node *new_entry = malloc(sizeof(node));
        table[hash(buffer)] = new_entry;
        new_entry->next = ptr;
        strcpy(new_entry->word, buffer);
        words++;
    }

    // Close the dictionary file
    fclose(source);
    free(buffer);
    return true;
}

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

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


// Implements a dictionary's functionality


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


// TODO: Choose number of buckets in hash table
const unsigned int N = 26;


int words = 0;


// Hash table
node *table[N];


// Returns true if word is in dictionary, else false
bool check(const char *word)
{
    // TODO
    node *ptr = table[hash(word)];
    while (ptr != NULL)
    {
        if (strcasecmp(word, ptr->word) == 0)
        {
            return true;
        }
            ptr = ptr->next;
    }
    return false;
}


// Hashes word to a number
unsigned int hash(const char *word)
{
    // TODO: Improve this hash function
    return toupper(word[0]) - 'A';
}


// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
    // Open the dictionary file
    FILE *source = fopen(dictionary, "r");
    if(source == NULL)
    {
        return false;
    }
    char *buffer = malloc(LENGTH + 1);
    if (buffer == NULL)
    {
        return false;
    }


    // Read each word in the file
    while(fscanf(source, "%s", buffer) != EOF)
    {
        // Add each word to the hash table
        node *ptr = table[hash(buffer)];
        node *new_entry = malloc(sizeof(node));
        table[hash(buffer)] = new_entry;
        new_entry->next = ptr;
        strcpy(new_entry->word, buffer);
        words++;
    }


    // Close the dictionary file
    fclose(source);
    free(buffer);
    return true;
}


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


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

Valgrind给我的错误如下:

==49523== 
==49523== HEAP SUMMARY:
==49523==     in use at exit: 0 bytes in 0 blocks
==49523==   total heap usage: 143,097 allocs, 143,097 frees, 8,023,302 bytes allocated
==49523== 
==49523== All heap blocks were freed -- no leaks are possible
==49523== 
==49523== For lists of detected and suppressed errors, rerun with: -s
==49523== ERROR SUMMARY: 143091 errors from 1 contexts (suppressed: 0 from 0)

Asking for help...

/home/ubuntu/.local/share/help50/cs50/helpers/helpers/_common.py:1: SyntaxWarning: invalid escape sequence '\/'
  FILE_PATH = "(?:(?:.*)\/(?:[^/]+)\/)?"
/home/ubuntu/.local/share/help50/cs50/helpers/helpers/valgrind.py:81: SyntaxWarning: invalid escape sequence '\d'
  "are definitely lost in loss record [\d,]+ of [\d,]+$", line)
==49523== Invalid read of size 8
==49523==    at 0x109B52: unload (dictionary.c:104)
==49523==    by 0x10970F: main (speller.c:153)

Looks like you're trying to access 8 bytes of memory that isn't yours? Did you try to index into an array beyond its bounds? Take a closer look
at line 104 of dictionary.c.

在第 104 行,我正在运行一个循环以释放链表中的所有内存。在过去的程序中,我使用了非常类似的循环来释放内存。释放当前节点,同时将其下一个节点的地址存储在临时节点中,然后对下一个节点重复相同的过程。

c cs50
1个回答
0
投票

问题就在这里:

tmp = ptr;
free(ptr);
ptr = tmp->next;

问题在于,赋值

tmp = ptr
不会创建
ptr
所指向的节点的副本,它只创建指针的副本。存储在
ptr
中的值。

这意味着您将有两个指针,

ptr
tmp
,指向内存中完全相同的对象。

当您调用

free(ptr)
时,这两个指针都会变得无效,并且取消引用其中任何一个(就像您对
tmp->next
所做的那样)将导致 未定义的行为

解决方案相当简单:更改执行操作的顺序:

tmp = ptr;
ptr = tmp->next;
free(tmp);
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.