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