循环单链接列表中的内存释放

问题描述

我目前正在刷新有关数据结构的知识。今天,我决定看一下链接列表。我已经完成了单链表和双链表的基本概念。但是,在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);
}

解决方法

您将head设置为等于one。然后,将p设置为等于head,因此将p设置为等于one。然后,您free(p),也free(one)。因此,您可以释放已经释放的已分配块。

此外,这段代码是令人迷惑的:

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

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

,

这里可能有两个错误。

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

我想您实际上是想要p->next = head

,

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

public Cell(int x,int y) {
    super(x,y,size,size);
    random_int = (int) (Math.random() * (maxyellow - minyellow + 1) + minyellow);
}

void paint(Graphics g,Point mousePos) {      
    if (contains(mousePos)) {
        g.setColor(Color.GRAY);
    } 
    else {
        g.setColor(Color.getHSBColor(255,random_int,60));
    }
    g.fillRect(x,size);
    g.setColor(Color.BLACK);
    g.drawRect(x,size);
}

您忘记了指针只是引用某个内存位置的数字。如果要使用指针(在这种情况下为nodeSL *p; p = malloc(sizeof(nodeSL)); p = head; // ... free(p) )来遍历列表,则无需从系统请求内存。

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

此外,您已分配内存,将其存储在p中,并通过在p中存储其他值立即泄漏该内存。

所以,只要不这样做,就可以了。