【问题标题】:Memory Deallocation in Circular Singly Linked List循环单链表中的内存释放
【发布时间】:2020-12-08 05:02:43
【问题描述】:

我目前正在更新我的数据结构知识。今天我决定看看链接列表。我已经完成了单链表和双链表的基本概念。但是,我在 C 中实现循环单链表时遇到了一个小问题。

在创建具有 3 个节点的循环单链表并打印其层次结构后,我想释放节点的内存。但是,每当我尝试运行代码时,都会引发异常。据我了解,问题与free(one); 行有关。正如您在我的代码中看到的那样,我什至尝试预先断开节点之间的链接。这个问题背后的原因是什么,是因为我以错误的方式释放循环链表中的内存吗?如果不是,应该通过什么方法来解决这个问题?

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

typedef struct NodeSL nodeSL;

struct NodeSL{
    int data;
    nodeSL *next;
};

void circularLinkedList();

int main(){

    /* Circular Link List Example */
    circularLinkedList();

    return 0;
}

void circularLinkedList(){
    /* Initializing the nodes. */
    nodeSL *head,*one,*two,*three;

    /* Allocating the memory. */
    one=(nodeSL*)malloc(sizeof(nodeSL));
    two=(nodeSL*)malloc(sizeof(nodeSL));
    three=(nodeSL*)malloc(sizeof(nodeSL));

    /* Assigning data values. */
    one->data=1;
    two->data=2;
    three->data=3;

    /* Connecting the nodes. */
    one->next=two;
    two->next=three;
    three->next=one;

    /* Saving the address of the first node in head. */
    head=one;

    nodeSL *p;
    int flag=1;
    p=(nodeSL*)malloc(sizeof(nodeSL));
    p=head;
    printf("THIS IS AN EXAMPLE OF A CIRCULAR LINKED LIST!\n");
    printf("Head has the address %u\n",head);
    while (flag) {
        printf("Data: %d",p->data);
        printf("\tAdress: %u",p);
        printf("\tPoints Forward to the Address: %u\n",p->next);  
        p=p->next;
        if(p==one)
        {
            flag=0;
        }
    }
    printf("\n\n");
    /* Deallocating the memory. */
    three->next=NULL;
    two->next=NULL;
    one->next=NULL;
    head=NULL;
    free(p);
    free(two);
    free(three);
    free(one);
}

【问题讨论】:

  • 我建议运行 valgrind 来跟踪内存分配问题
  • 注明。我目前正在使用 Visual Studio Code 进行编码。我发现它有自己的内存跟踪器功能。无论如何,我会确保将 valgrind 安装到我的 Ubuntu 上。感谢您的建议。

标签: c linked-list dynamic-memory-allocation free circular-list


【解决方案1】:

您正在陷入一些初学者在使用指针时遇到的经典陷阱。

nodeSL *p;
p = malloc(sizeof(nodeSL));
p = head;

// ...

free(p)

您忘记了指针只是引用某个内存位置的数字。如果您想使用指针(在本例中为 p)来遍历您的列表,则无需向系统请求内存。

简而言之,您在这里拥有的是双重免费。你释放了p,然后你释放了one,这与循环后p的值相同。如果您使用调试器,您会在这一行看到错误。

此外,您分配了内存,将其存储在 p 中,然后通过在 p 中存储不同的值立即泄漏该内存。

所以,不要这样做,你会没事的。

【讨论】:

  • 你完全正确!在过去的 6.5 个小时里,我一直在不停地编码,我想我可能已经遭受了“脑疲劳”。现在我看到了,我不知道为什么我为那个指针请求内存。我想我认为该指针是错误的节点。因为我认为它是一个节点,所以我试图释放它,没有意识到你刚才所说的 - p 也指向一个 -。最后,老实说,这是我第一次向您学习“泄漏”的概念 :) 我对动态内存分配的使用也很陌生。我将确保检查更多有关此主题的信息。非常感谢!
【解决方案2】:

您将head 设置为等于one。然后设置p 等于head,因此设置p 等于one。然后你free(p) 还有free(one)。所以你释放了一个你已经释放的分配块。

另外,这段代码很神秘:

    p=(nodeSL*)malloc(sizeof(nodeSL));
    p=head;

为什么你分配一个新节点只是为了然后将p 更改为指向head 并泄漏你刚刚分配的节点?您希望p 指向head 已经指向的节点,还是希望p 指向新分配的节点?下定决心。

【讨论】:

  • 没错!这解决了问题。我现在看到我试图做的事情是多么愚蠢。同样对于“神秘代码”部分,我想我只是忘记了我正在处理一个指针,并假设 p 是一个节点,所以我试图为此分配内存。你也击败了@Louis Go。好样的! :) (非常感谢您的快速回复)
【解决方案3】:

这里有两个可能的错误。

  1. pheadheadone,释放 pone 意味着释放指针两次。
    /* Saving the address of the first node in head. */
    head=one;
  1. 内存因分配而泄漏,并立即再次分配给它。
    p=(nodeSL*)malloc(sizeof(nodeSL));
    p=head; // p is leaked.

我想你实际上想要p-&gt;next = head

【讨论】:

  • 我领先你 23 秒。
  • @DavidSchwartz 我通过猜测 OP 的意图打败了你! :)
  • 这不是一场比赛:P
  • @paddy 更像是一个派对 :)
  • 你成功了。我没有看到 p 和 head 都指向“一”。另外我想我认为 p 是一个节点,所以这就是为什么为它分配内存的原因。然后一旦我开始处理 while 循环,我就忘了删除它。非常感谢您的快速回答!
猜你喜欢
  • 1970-01-01
  • 2012-10-31
  • 2021-09-01
  • 2011-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-30
相关资源
最近更新 更多