【问题标题】:cs50 pset5 memory leak when in unload function, when freeing memorycs50 pset5 在卸载功能时内存泄漏,在释放内存时
【发布时间】:2020-08-18 17:10:08
【问题描述】:

我目前正在处理cs50 pset5。

我在尝试释放程序中的所有内存时遇到了内存泄漏。
该错误似乎发生在我的unload 函数中,其中malloc 用于指针cursor。
如果有人可以向我提供有关如何解决此问题的指导,请告诉我。
我还为我的代码提供了 cmets 以突出显示它在做什么。

// 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 = 50;

node *table[N] = {NULL};

// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
    // allocate memory for struct type `node` pointer 
    node *cursor = (node*)malloc(sizeof(node));                 // MEMORY LEAK happens here !!!! :(
    node *tmp = (node*)malloc(sizeof(node));

    // if memory cannot be allocated successfully, return false
    if (cursor == NULL || tmp == NULL)
    {
        return false;
    }

    // iterate the table for N'times (N = 50, for now)
    for (int i = 0; i < N; i++)
    {
        // if the table has nothing inside the i'th bucket, return false 
        // this means, table has no linked list inside i'th bucket 
        if (table[i] == NULL)
        {
            continue;
        }
        else
        {
            // assign tmp pointer to the head node, and cursor to anything next to tmp 
            tmp = table[i];
            cursor = tmp;
            cursor = cursor->next;
            // free memory for tmp pointer 
            free(tmp);

            // continue traversing the linked list until cursor pointer points to NULL (end of the linked list)
            while (cursor != NULL)
            {
                tmp = cursor;
                cursor = cursor->next;
                free(tmp);
            }
        }
    }

    // free memory for cursor
    free(cursor);
    return true;
}

我得到的错误,运行后,help50 valgrind ./speller dictionaries/small texts/cat.txt。

==14685== Memcheck, a memory error detector
==14685== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==14685== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==14685== Command: ./speller dictionaries/small texts/cat.txt
==14685== 
32
==14685== Invalid write of size 1
==14685==    at 0x40121F: hash (dictionary.c:67)
==14685==    by 0x401354: load (dictionary.c:99)
==14685==    by 0x400A2B: main (speller.c:41)
==14685==  Address 0x55cc88a is 2 bytes after a block of size 8 alloc'd
==14685==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14685==    by 0x4011D5: hash (dictionary.c:61)
==14685==    by 0x401354: load (dictionary.c:99)
==14685==    by 0x400A2B: main (speller.c:41)
==14685== 
==14685== Invalid read of size 1
==14685==    at 0x40122C: hash (dictionary.c:68)
==14685==    by 0x401354: load (dictionary.c:99)
==14685==    by 0x400A2B: main (speller.c:41)
==14685==  Address 0x55cc88a is 2 bytes after a block of size 8 alloc'd
==14685==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14685==    by 0x4011D5: hash (dictionary.c:61)
==14685==    by 0x401354: load (dictionary.c:99)
==14685==    by 0x400A2B: main (speller.c:41)
==14685== 
19

MISSPELLED WORDS

47
A
32
20
is
27
not
47
a
==14685== Invalid write of size 1
==14685==    at 0x40121F: hash (dictionary.c:67)
==14685==    by 0x401124: check (dictionary.c:32)
==14685==    by 0x400D50: main (speller.c:114)
==14685==  Address 0x55cdf9a is 2 bytes after a block of size 8 alloc'd
==14685==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14685==    by 0x4011D5: hash (dictionary.c:61)
==14685==    by 0x401124: check (dictionary.c:32)
==14685==    by 0x400D50: main (speller.c:114)
==14685== 
==14685== Invalid read of size 1
==14685==    at 0x40122C: hash (dictionary.c:68)
==14685==    by 0x401124: check (dictionary.c:32)
==14685==    by 0x400D50: main (speller.c:114)
==14685==  Address 0x55cdf9a is 2 bytes after a block of size 8 alloc'd
==14685==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14685==    by 0x4011D5: hash (dictionary.c:61)
==14685==    by 0x401124: check (dictionary.c:32)
==14685==    by 0x400D50: main (speller.c:114)
==14685== 
19

WORDS MISSPELLED:     4
WORDS IN DICTIONARY:  2
WORDS IN TEXT:        6
TIME IN load:         0.03
TIME IN check:        0.00
TIME IN size:         0.00
TIME IN unload:       0.00
TIME IN TOTAL:        0.03

==14685== 
==14685== HEAP SUMMARY:
==14685==     in use at exit: 1,000 bytes in 9 blocks
==14685==   total heap usage: 23 allocs, 14 frees, 10,944 bytes allocated
==14685== 
==14685== 56 bytes in 1 blocks are definitely lost in loss record 1 of 4
==14685==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14685==    by 0x4013F1: unload (dictionary.c:128)
==14685==    by 0x400ED0: main (speller.c:154)
==14685== 
==14685== 56 bytes in 1 blocks are definitely lost in loss record 2 of 4
==14685==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14685==    by 0x4013FF: unload (dictionary.c:129)
==14685==    by 0x400ED0: main (speller.c:154)
==14685== 
==14685== 336 bytes in 6 blocks are definitely lost in loss record 3 of 4
==14685==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14685==    by 0x401131: check (dictionary.c:33)
==14685==    by 0x400D50: main (speller.c:114)
==14685== 
==14685== 552 bytes in 1 blocks are still reachable in loss record 4 of 4
==14685==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14685==    by 0x5258E49: __fopen_internal (iofopen.c:65)
==14685==    by 0x5258E49: fopen@@GLIBC_2.2.5 (iofopen.c:89)
==14685==    by 0x4012DE: load (dictionary.c:83)
==14685==    by 0x400A2B: main (speller.c:41)
==14685== 
==14685== LEAK SUMMARY:
==14685==    definitely lost: 448 bytes in 8 blocks
==14685==    indirectly lost: 0 bytes in 0 blocks
==14685==      possibly lost: 0 bytes in 0 blocks
==14685==    still reachable: 552 bytes in 1 blocks
==14685==         suppressed: 0 bytes in 0 blocks
==14685== 
==14685== For counts of detected and suppressed errors, rerun with: -v
==14685== ERROR SUMMARY: 15 errors from 7 contexts (suppressed: 0 from 0)

Asking for help...

==14685== 56 bytes in 1 blocks are definitely lost in loss record 1 of 4
==14685==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14685==    by 0x4013F1: unload (dictionary.c:128)
==14685==    by 0x400ED0: main (speller.c:154)

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

那么为什么会发生内存泄漏呢?
A memory leak happens when a programmer creates a memory from heap but forgets to free it.

但是,在我的代码中,我已经释放了 cursor 和 tmp 指针在使用后。
我不知道为什么会遇到错误,虽然我在函数结束时释放它。

【问题讨论】:

    标签: c memory-leaks hashtable cs50


    【解决方案1】:

    是的,“内存泄漏发生在这里!!!”如你所说。

    您分配了两个缓冲区,但后来它们的指针被table[i] 覆盖而没有被释放。这是内存泄漏。

    为避免内存泄漏,请停止分配未使用的缓冲区。

    部分

        // allocate memory for struct type `node` pointer 
        node *cursor = (node*)malloc(sizeof(node));                 // MEMORY LEAK happens here !!!! :(
        node *tmp = (node*)malloc(sizeof(node));
    
        // if memory cannot be allocated successfully, return false
        if (cursor == NULL || tmp == NULL)
        {
            return false;
        }
    

    应该只是

        // allocate memory for struct type `node` pointer 
        node *cursor;
        node *tmp;
    

    指针的内存分配在堆栈上。

    也是部分

        // free memory for cursor
        free(cursor);
    

    应该被删除,因为列表已经被释放,并且光标的内存将在从函数返回时自动释放(从堆栈中)。

    【讨论】:

    • 感谢您的回答!您的回答确实很有趣,我想问您另一个问题,关于您在这里写的内容。所以,你说overwritten by table[i] without being freed,我相信你指的是tmp = table[i];上的代码。为什么我不能覆盖指针?实际上,我想做的是让tmp 指向table[i] 指向的任何东西。这意味着,我只是将内存地址table[i] 传递给tmp。为什么不允许这样做? table[i]和tmp都是相同的数据类型,都是指向node的指针。(node是struct类型)
    • 简单地将内存地址table[i] 持有到tmp 是允许的。不好的是分配未使用的缓冲区并通过分配新地址而不释放缓冲区来丢弃其存储在tmp 中的地址。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-06-16
    • 2020-10-18
    • 1970-01-01
    • 1970-01-01
    • 2014-09-19
    • 1970-01-01
    • 2012-06-08
    相关资源
    最近更新 更多