【问题标题】:how to free memory for doubly linked list program in c如何在c中为双向链表程序释放内存
【发布时间】:2013-01-04 20:24:12
【问题描述】:

在过去的几天里,我正在研究我的 c\c++ 技能。我正在阅读我的数据结构书,然后我想为什么不实现双向链表程序。我写了程序;令人惊讶的是它也可以正常工作,但是,我不确定我是否写对了。我无法弄清楚如何释放我分配的内存。请帮我解决这些问题。

另外,如果有人能解释一下这个“while(linkNode!=0)”,我将非常感激。

#include<stdio.h>
#include<malloc.h>

struct node
{
    int x;
    struct node * next;
    struct node * prev;
};

struct head
{
    unsigned int count;
    struct node * hd;
    struct node * tl;

};


void main()
{
    int i =0;

    struct node * linkNode;
    struct head *hdd;

    hdd = (head *)malloc(sizeof(head));

    linkNode = (node *) malloc(sizeof(node));
    hdd->count = 1;
    hdd->hd = linkNode;
    linkNode->prev = 0;
    linkNode->next = 0;
    linkNode->x = 0;


    for(;i<10;i++)
    {
        linkNode->next = (node *) malloc(sizeof(node));
        linkNode->next->prev = linkNode;
        linkNode = linkNode->next;
        linkNode->next = 0;
        linkNode->x = i;
        hdd->count+=1;
        hdd->tl = linkNode;

    }

    linkNode = hdd->hd;
    printf("priniting in next direction\n");
    while(linkNode!=0)
    {
        printf("%d\n",linkNode->x);
        linkNode = linkNode->next;
    }


    linkNode = hdd->tl;
    printf("priniting in prev direction\n");
    while(linkNode!=0)
    {
        printf("%d\n",linkNode->x);
        linkNode = linkNode->prev;
    }

    linkNode = hdd->hd;
    while(linkNode!=0)
    {
        free(linkNode->prev);
        linkNode = linkNode->next;

    }

    free(hdd);


}

【问题讨论】:

    标签: c list memory linked-list allocation


    【解决方案1】:

    您已经从链表尾部以相反的顺序释放分配给链表节点的内存。这条线正在这样做。

    free(linkNode->prev);
    

    您的程序中存在内存泄漏。列表中的最后一个节点未被释放。

    只包含

    free(linkNode);
    

    在释放硬盘之前。

    解释:

    while(linkNode!=0)
    

    这是为了确保您取消引用 NULL 指针。由于取消引用 NULL 指针可能会导致 undefined behaviours

    这些是取消引用操作

    linkNode->x
    linkNode->prev
    

    【讨论】:

    • 感谢 Sibrajas 的快速回复。你能告诉我编译器实际上是如何转换这个语句的吗?我问这个是因为我对反向遍历和正常遍历使用相同的语句。另外我只是想澄清一下我的程序正在释放它分配的所有内存还是有任何内存泄漏?
    • 您使用l = l-&gt;next 进行正向遍历,使用l = l-&gt;prev 进行反向遍历。所以,你不是对两者都使用相同的。事实上,有一个泄漏——你泄漏了最后一个节点。
    • @user1289810 这个分配和释放与编译无关。所有这些都是在运行时。当然 malloc 在堆中分配内存或用于动态内存分配。 .您正在按照前向顺序释放内存。是的 。我在这里看到内存泄漏。对于列表的最后一个节点。我会编辑我的答案。
    • 谢谢你们的澄清。因此,如果在 while 循环之后我说 free(linkNode) 或 free(hd->tl) 它确实释放了我创建的所有内存,对。再次感谢@Useless 和 Sibrajas
    【解决方案2】:

    您的链接列表如下所示:

    +------+----+----+
    | Head | hd | tl | ---------->--------
    +------+----+----+                    \
             |               ---->------   |           NULL
             |             /            \  |             |
         +------+-----+------+------+   +------+-----+------+------+
         | Node | x=0 | next | prev |   | Node | x=1 | next | prev |
         +------+-----+------+------+   +------+-----+------+------+
             |                  |                             |
              \                NULL                          /
               -----------------------<----------------------
    

    (我已将其简化为两个节点)。

    现在,我们可以写出这段代码的作用:

    linkNode = hdd->hd;
    while(linkNode!=0) {
        free(linkNode->prev);
        linkNode = linkNode->next;
    }
    
    1. linkNode = hdd-&gt;hdlinkNode 指向第一个节点
    2. (linkNode!=0)为真(第一个节点不为NULL),所以我们进入while循环
    3. free(linkNode-&gt;prev)hdd-&gt;hd-&gt;prev == NULL 以来调用 free(NULL)(您明确地设置了第一个节点)。这很好,但什么也没做。
    4. linkNode = linkNode-&gt;nextlinkNode 指向最后一个节点
    5. linkNode!=0 仍然为真(最后一个节点也不是 NULL),所以我们再循环一次
    6. free(linkNode-&gt;prev) 释放前一个节点(即第一个节点)
    7. linkNode = linkNode-&gt;next 离开 linkNode == NULL
    8. linkNode!=0 现在为 false,因此循环终止。

    所以,我们释放了除了最后一个节点之外的所有节点。没有节点的prev 成员指向该节点,因此调用free(linkNode-&gt;prev) 永远无法释放它。但是,您可以通过 hdd-&gt;tl 释放它。

    【讨论】:

    • 乏味,但有时图片只是更清晰(甚至是ASCII艺术)
    • 在记事本或其他工具中?
    猜你喜欢
    • 2012-10-31
    • 2011-05-04
    • 1970-01-01
    • 1970-01-01
    • 2012-05-27
    • 1970-01-01
    • 1970-01-01
    • 2022-01-21
    • 1970-01-01
    相关资源
    最近更新 更多