Valgrind新手,似乎无法让它快乐

时间:2015-06-14 18:37:08

标签: c hashtable valgrind cs50

我正在线上完成CS50课程,手头的任务是将字典加载到内存中(我使用链式哈希表数据结构),并检查文本文件的内容与词典。我写了一个load()函数,它加载字典文件并将每个单词存储到内存中。加载所有单词时,该函数返回true。 Valgrind没有显示内存泄漏。问题是我有一个荒谬的读/写错误。它帮助我确定了他们似乎来自哪里,我一直在搜索互联网,但似乎无法做出正面或反面。

以下是相关代码:

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define HASH_SIZE 10
#define LENGTH 45

typedef struct node
{
    char* word;
    struct node* next;
} node;

// Globals
node* hashTable[HASH_SIZE];
unsigned int dictionary_size = 0;

/**
 * Loads dictionary into memory.  Returns true if successful else false.
 **/
bool load(const char* dictionary)
{
    // Initialize variables
    char currentWord[LENGTH + 1];
    int tableIndex;

    // Open dictionary
    FILE* dict = fopen(dictionary, "r");
    if (dict == NULL)
        return false;

    while(fscanf(dict, "%s", currentWord) == 1)
    {
        // Get hash value of word
        tableIndex = hash(currentWord);

        // Initialize new node
        node* newNode = malloc(sizeof(node));
        newNode->word = malloc((strlen(currentWord) + 1) * sizeof(char));
        if (newNode == NULL || newNode->word == NULL)
        {
            printf("Error: Out of memory\n");
            return false;
        }

        // Copy word into new node
        strcpy(newNode->word, currentWord);
        newNode->next = NULL;

        // If no collision, hash word into head of list
        if (hashTable[tableIndex] == NULL)
            hashTable[tableIndex] = newNode;

        // Create a pointer and move down list
        else
        {
            node* ptrNode = hashTable[tableIndex];

            while (ptrNode->next != NULL)
                ptrNode = ptrNode->next;

            // Append node to end of linked list
            ptrNode->next = newNode;
        }

        // Increase dictionary size
        dictionary_size++;

        // Free word member before actual node
        free(newNode->word);
        free(newNode);
    }

    // Close dictionary and return true
    fclose(dict);
    return true;
}

我的Valgrind:

==32487== Invalid read of size 4
==32487==    at 0x8048989: load (my_new_test.c:120)
==32487==    by 0x804873D: main (my_new_test.c:53)
==32487==  Address 0x423b30c is 4 bytes inside a block of size 8 free'd
==32487==    at 0x402B3D8: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-   linux.so)
==32487==    by 0x80489D3: load (my_new_test.c:132)
==32487==    by 0x804873D: main (my_new_test.c:53)
==32487== 
==32487== Invalid write of size 4
==32487==    at 0x80489AA: load (my_new_test.c:124)
==32487==    by 0x804873D: main (my_new_test.c:53)
==32487==  Address 0x423b30c is 4 bytes inside a block of size 8 free'd
==32487==    at 0x402B3D8: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==32487==    by 0x80489D3: load (my_new_test.c:132)
==32487==    by 0x804873D: main (my_new_test.c:53)
==32487== 
==32487== Invalid read of size 4
==32487==    at 0x8048999: load (my_new_test.c:121)
==32487==    by 0x804873D: main (my_new_test.c:53)
==32487==  Address 0x423bb24 is 4 bytes inside a block of size 8 free'd
==32487==    at 0x402B3D8: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==32487==    by 0x80489D3: load (my_new_test.c:132)
==32487==    by 0x804873D: main (my_new_test.c:53)

==32487== HEAP SUMMARY:
==32487==     in use at exit: 0 bytes in 0 blocks
==32487==   total heap usage: 286,183 allocs, 286,183 frees, 2,584,308 bytes        allocated
==32487== 
==32487== All heap blocks were freed -- no leaks are possible
==32487== 
==32487== For counts of detected and suppressed errors, rerun with: -v
==32487== ERROR SUMMARY: 10000000 errors from 3 contexts (suppressed: 0 from  0)

我仍然非常原始使用Valgrind但是从我收集的内容我的问题似乎是在else语句中,主要是创建的指针(node * ptrNode)。任何人都可以看到我没有看到的东西吗?任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:3)

问题很可能是这两行:

free(newNode->word);
free(newNode);

您刚刚将节点添加到哈希表中,然后立即释放它,使哈希表中的指针无效,因为它们现在指向free'd数据。