Pset5(Speller)奇怪的Valgrind内存错误,没有泄漏。

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

我读过其他关于pset5 Valgrind内存错误的帖子,但这并没有帮助我。我得到的是0个泄漏,而不是这个。

==1917== 条件跳转或移动取决于未初始化的值 看起来你在尝试使用一个可能没有值的变量?仔细看看 dictionary.c 的第 34 行。

错误指的是第34行: lower[i] = tolower(word[i])。

为了提供上下文,下面的代码试图检查一个词是否存在于已经上传到哈希表中的字典中。我试图将想要的单词转换为小写,因为所有的字典单词也都是小写的,这样它们的哈希值就会相同。程序成功地完成了所有的任务,但是却遇到了这些内存错误。

有什么提示,为什么Valgrind会对我发火?谢谢你

 // Returns true if word is in dictionary else false
bool check(const char *word)
{
    char lower[LENGTH + 1]; 

   //Converts word to lower so the hashes of the dictionary entry and searched word would match
    for (int i = 0; i < LENGTH + 1; i++)
    {
        lower[i] = tolower(word[i]);
    }

    // Creates node from the given bucket
    node *tmp = table[hash(lower)];

    // Traverses the linked list
    while (tmp != NULL)
    {
        if (strcasecmp(word, tmp->word) == 0)
        {
            return true;
        }

        tmp = tmp->next;
    }

    return false;
}

下面是整个dictionary.c文件。

// Implements a dictionary's functionality
#include <string.h>
#include <strings.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.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 26^3
const unsigned int N = 17576;

// Hash table
node *table[N];
int count = 0;

// Returns true if word is in dictionary else false
bool check(const char *word)
{
    char lower[LENGTH + 1]; 

   //Converts word to lower so the hashes of the dictionary entry and searched word would match
    for (int i = 0; i < LENGTH + 1; i++)
    {
        lower[i] = tolower(word[i]);
    }

    // Creates node from the given bucket
    node *tmp = table[hash(lower)];

    // Traverses the linked list
    while (tmp != NULL)
    {
        if (strcasecmp(word, tmp->word) == 0)
        {
            return true;
        }

        tmp = tmp->next;
    }

    return false;
}

// Hashes word to a number
unsigned int hash(const char *word)
{
    // Modified hash function by Dan Berstein taken from http://www.cse.yorku.ca/~oz/hash.html
    unsigned int hash = 5381;
    int c;

    while ((c = *word++))
    {
        hash = (((hash << 5) + hash) + c) % N; /* hash * 33 + c */
    }

    return hash;
}

// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
    FILE *inptr = fopen(dictionary, "r");

    if (dictionary == NULL)
    {
        printf("Could not load %s\n.", dictionary);
        return false;
    }

    // Create a char array to temporarily hold the new word (r stands for read)
    char r_word[N+1];

    // Until the end of file
    while (fscanf(inptr, "%s", r_word) != EOF)
    {
        // Increments count
        count++;

        // Create a node
        node *new_node = malloc(sizeof(node));

        if (new_node == NULL)
        {
            unload();
            return false;
        }

        strcpy(new_node->word, r_word);

         // Hash the node
        int index = hash(new_node->word);
        // Places the node at the right index
        new_node->next = table[index];
        table[index] = new_node;
    }

    fclose(inptr);

    return true;
}

// Returns number of words in dictionary if loaded else 0 if not yet loaded
unsigned int size(void)
{
    if (&load == false)
    {
        return '0';
    }
    else
    {
        return count;
    }

}

// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
    // Interates over the array
    for (int i = 0; i < N; i++)
    {
        node *head = table[i];

        while (head != NULL)
        {
            node *tmp = head;
            head = head->next;
            free(tmp);
        }
    }

    return true;
}
valgrind cs50
1个回答
1
投票

这个循环迭代了 最大长度word-

for (int i = 0; i < LENGTH + 1; i++)
{
    lower[i] = tolower(word[i]);
}

但如果你看看如何 word 是创建

while (fscanf(inptr, "%s", r_word) != EOF)
{
    // Increments count
    count++;
    // Create a node
    node *new_node = malloc(sizeof(node));
    if (new_node == NULL)
    {
        unload();
        return false;
    }
    strcpy(new_node->word, r_word);

注意,变量 r_word,不一定完全是长度 LENGTH + 1. 那么,你到底有什么 word 是N个字符,其中N是 未必 LENGTH + 1,可以少一点。

所以,循环整个 0 -> LENGTH + 1 对于短于 LENGTH + 1. 你在数组槽上没有值,它们有垃圾值。

有什么办法呢?这正是为什么c字符串有 \0-

for (int i = 0; word[i] != '\0'; i++)
{
    lower[i] = tolower(word[i]);
}

这将在到达NULL字符时立即停止循环,你一定已经知道,NULL字符标志着一个字符串的结束--也就是一个char数组。

你的代码中可能还有更多的错误。但对于你的特殊问题--读出界就是答案。

© www.soinside.com 2019 - 2024. All rights reserved.