Search code examples
clinked-listdynamic-memory-allocationfreecircular-list

Memory Deallocation in Circular Singly Linked List


I'm currently refreshing my knowledge on data structures. Today I've decided to take a look at the Linked Lists. I've finished the basic concepts of singly and doubly linked lists. However I've encountered a small problem when I was implementing circular singly linked list in C.

After creating the circular singly linked list with 3 nodes and printing its hierarchy, I wanted to deallocate the memory of the nodes. However whenever I try to run the code, an exception gets thrown. From what I've understood, the problem is related to the line free(one);. As you can see in my code, I even tried to break the links between the nodes beforehand. What is the reason behind this problem, is it because I'm freeing the memory in a circular linked list in a wrong way? If not, what method should be followed to get rid of this problem?

#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);
}

Solution

  • You are falling into a classic trap that some beginners encounter when using pointers.

    nodeSL *p;
    p = malloc(sizeof(nodeSL));
    p = head;
    
    // ...
    
    free(p)
    

    You forget that a pointer is just a number that references some memory location. If you want to use a pointer (in this case, p) to iterate over your list, you do NOT need to request memory from the system.

    In short, what you have here is a double-free. You free p, and then later you free one, which is the same value that p has after your loop. If you used a debugger, you would see the error on this line.

    Furthermore, you allocated memory, stored it in p and immediately leaked that memory by storing a different value in p.

    So, just don't do this, and you'll be fine.