释放哈希表分配的内存时出现“ free():无效指针”错误

时间:2018-08-05 08:46:07

标签: c

编辑:

我已经通过valgrind运行了程序,该程序指向了我在此处包含的两个函数:

==6768== Invalid free() / delete / delete[] / realloc()
==6768==    at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6768==    by 0x42187C: free_memory (test4.c:232)
==6768==    by 0x42087E: main (test4.c:93)
==6768==  Address 0x10855f8 is 0 bytes inside data symbol "hash_table"
==6768== 
==6768== Invalid free() / delete / delete[] / realloc()
==6768==    at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6768==    by 0x421856: free_memory (test4.c:224)
==6768==    by 0x42087E: main (test4.c:93)
==6768==  Address 0x1085708 is 272 bytes inside data symbol "hash_table"
==6768== 
==6768== 
==6768== HEAP SUMMARY:
==6768==     in use at exit: 36,504 bytes in 676 blocks
==6768==   total heap usage: 679 allocs, 679 frees, 36,666 bytes allocated
==6768== 
==6768== 36,504 bytes in 676 blocks are definitely lost in loss record 1 of 1
==6768==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6768==    by 0x4208C9: init_table (test4.c:105)
==6768==    by 0x42073D: main (test4.c:44)
==6768== 
==6768== LEAK SUMMARY:
==6768==    definitely lost: 36,504 bytes in 676 blocks
==6768==    indirectly lost: 0 bytes in 0 blocks
==6768==      possibly lost: 0 bytes in 0 blocks
==6768==    still reachable: 0 bytes in 0 blocks
==6768==         suppressed: 0 bytes in 0 blocks
==6768== 
==6768== For counts of detected and suppressed errors, rerun with: -v
==6768== ERROR SUMMARY: 677 errors from 3 contexts (suppressed: 0 from 0)

大家好。如果您有时间,我有一个有趣的问题。几天以来,free()的{​​{1}}函数一直出现错误。我的代码有些大,因此我对其进行了测试,以使其在缩小版中得到相同的错误。我知道问题出在哪里,但我无法解决。非常感谢所有帮助。完整的错误文字:

stdlib.h

代码包含一个数据结构,该数据结构以单词的第一个和第二个字母的字母索引作为键值来索引单词,并将单词本身存储在由位于相应索引位置的节点头指向的链接列表中。这是一个非常简单的想法。就像一个伟人曾经说过的:谈话很便宜,请告诉我代码。开始阅读从(1)到(3)的数据结构定义,这将更有意义:

*** Error in `./sample': free(): invalid pointer: 0x0000000001084078 ***
Aborted

1 个答案:

答案 0 :(得分:3)

该代码中有很多问题。

您的错误可能来自此件:

    for (int j = 0; j < 26; j++)  // rows
    {
        // Address of the first node of the current linked list
        ptr = &table->columns[i].rows[j];

记住:该表是一个全局变量,不会动态分配。 ptr指向此静态变量的数组元素。

        while(1)
        {
            if(ptr->next)  // If node does not point to "NULL"
            {
                del_node = ptr;  // Guide the "del_node"
                ptr = ptr->next;  // Advance "ptr" to the next node
                free(del_node);  // Free the memory pointed by "del_node"
            }

在这里尝试释放数组中的节点。不是动态分配的内存位置。那不会飞。

看看您初始化表的方式,我们发现更多问题:

    for (int j = 0; j < 26; j++)  // For each row
    {
        // Allocate space for a new node, as the head of a linked list.
        // Max word length will be 45 letters, allocate that much space
        node *first_node = malloc(sizeof(char) * 46 + sizeof(node *));

您有46个字节的内存,无法使用node类型进行访问。

        // Assign new node with value of "none", and "next" (pointer) of NULL
        *first_node = (node) { .value = "none", .next = NULL };

虽然value是指向char的指针,但这可能有用。但是,如果您打算将动态分配的内存用于其他节点,则需要在以后释放它。这不适用于字符串文字。

        // Store this node in the current table cell
        table->columns[i].rows[j] = *first_node;

您复制分配的内存的内容(当然不带46个额外的字节),然后您就忘记了分配的内存。您将无法再释放它。

如果这些节点都是列表的头,则不应为它们分配内存,因为它们是静态的。