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.
You set head equal to one. Then you set p equal to head, which therefore sets p equal to one. Then you free(p) but also free(one). So you free an allocated block that you already freed.
Also, this code is mystifying:
p=(nodeSL*)malloc(sizeof(nodeSL));
p=head;
Why do you allocate a new node just to then change p to point to head and leak the node you just pointlessly allocated? Do you want p to point to the node that head already points to or do you want p to point to the newly-allocated node? Make up your mind.
There are two possible errors here.
p is head and head is one, and freeing p and one means deallocate a pointer twice.
/* Saving the address of the first node in head. */
head=one;
Memory leaked by allocating it and immediately assign to it again.
p=(nodeSL*)malloc(sizeof(nodeSL));
p=head; // p is leaked.
I presume you actually wants p->next = head.
Related
Suppose I have a standard linked list struct as follows:
struct Linked {
int data;
Linked* next;
}
I make a bunch of them in a loop by callocing the next pointer enough memory to store another Linked and initializing it. As per the norm with linked lists, I only maintain a pointer to the first node as follows:
struct Linked *first = make_list();
Now, I want to deallocate the memory held by the entire list. Can I call
free(first);
and have it release all the memory (including the memory allocated to all the next pointers), or do I have to do the deallocation from the end backwards?
There has to be one call to free() for each call to calloc(). So, you need to use a loop to free every element of your list in turn. You can choose to do the freeing backwards or forwards, but you'll probably find that forwards is easier:
void freelist(struct Linked *head)
{
while (head != NULL) {
struct Linked *tmp = head;
head = head->next;
free(tmp);
}
}
Note (and this is important) that you must read the value of head->next before freeing the node.
I created a linked list with ten nodes. I want to get the address of the first node I created in the linked list. I am getting incorrect address value for the first node. This is the code which I wrote :
#include "singlyLinkedList.h"
#include <stddef.h> //for NULL
#include <stdlib.h> //for malloc
#include <stdio.h> //for printf
node *pNode;
void CreateLinkedList()
{
int i;
pNode = (node*)malloc(sizeof(node)); //create space for first node []
for(i=0;i<10;i++)
{
pNode->element = i; //enter value [0]
printf("Value is %d addr is %p\n",pNode->element,pNode);
pNode->nextPtr = (node*)malloc(sizeof(node)); //[0]->[]->NULL
pNode = pNode->nextPtr;
}
pNode->nextPtr=NULL;
}
//Function to get first node address
void GetFirstNodeAddress()
{
pNode = pNode-10*(sizeof(node));
printf("\n *** Value is %p",pNode);
}
int main()
{
CreateLinkedList();
GetFirstNodeAddress();
}
You assume that the 10 malloc's you do will result in 10 consecutive addresses. You handle it as if it is an array, yet the elemenents of the linked list are independent.
The way these linked lists usually work is that you initialise them and keep the first pointer to be returned later. Then grow more elements on the tail. You can not walk backwards in a single linked list.
I gave a code example in an earlier post today
You don't use pointer arithmetic in linked list implementations, at least not trivial ones. And you're populating your list incorrectly. You need to retain the head pointer. This is one such way to do it:
// Note: do NOT invoke on a non-empty pNode list
void CreateLinkedList()
{
node **pp = &pNode;
int i;
for (i=0;i<10;++i)
{
*pp = malloc(sizeof(**pp));
(*pp)->element = i;
pp = &(*pp)->nextPtr;
}
*pp = NULL;
}
How It Works
Just like pNode is a pointer to a node, pp is a pointer to a node *. During the lifetime of the loop pp always holds the address of the next pointer about to be filled with a new node allocation. After the allocation and node setup, pp is filled with the address of the nextPtr pointer of the node just-created. This continues until the end of the fill. At that point the pointer addressed by pp is the tail nextPtr and should be null-terminated (which is what *pp = NULL does). Step through this code in a debugger to see better how it works.
Personally I would pass the address of the head pointer as a parameter, but this is one immediate way to get your code running.
Try printf("\n *** Value is %p",(void *) &pNode);. & is typically the easiest way to get pointer addresses
also from what I know: pNode = pNode-10*(sizeof(node)); is incorrect.
when you are doing pointers, they point to areas in memory that are not necessarily contiguous (following in order in memory). Meaning you could have one pointer pointing to memory blocks 5-10, which also has a pointer to memory blocks 83-88. If you want to get the first node, create a pNode rootNode and assign your first created pNode to that. Then you can traverse it in a while loop as well as printing out the address as listed above or whatever else you please.
I have created a program based on a linked-list where every node is a struct that holds an 8-byte integer and a pointer to the next node. The queue follows FIFO. It seems to work fine but I suspect the program could suffer from some kind of memory-leak or memory fragmentation in the heap. I may be wrong - hopefully!!! When a node is deleted in FIFO-order I use the library function free where I put the pointer of that node. I also set the pointer to the first and last node to NULL when the linked-list is empty.
But there is a thing that I do not understand and could be sign of a memory-leak.
Let say I create 3 nodes that holds 3 integers. The memoryaddresses of these nodes is as follows:
205888
206032
206056
Now I decide to delete these nodes and free resources to these three nodes.
And when I startover to add nodes - the first node do not start at address 205888, it starts at address 206056.
Does this reveal a memory-leak in my program?
Here is the function the destroy the node. It takes as argument the address to nodes that is to be deleted
static int destroy_node(node *node_ref) {
int data = 0;
data = node_ref->data;
free(node_ref);
return data;
}
and the struct
typedef struct node {
int data;
struct node *next;
} node;
If you free an area of memory, you cannot be sure what will be allocated for you next. So this behaviour basically does not show a memory leak.
There may be a memory leak in your code but you can not detect it using address of the allocated node.
To detect memory leak in your code you need tools like Valgrind
It would depend on the algorithm in the heap. Strictly speaking, this is "indeterminant" and out of your control. It could be a sign, but it's not evidence.
If I have a snippit of my program like this:
struct Node *node;
while(...){
node = malloc(100);
//do stuff with node
}
This means that every time I loop through the while loop I newly allocate 100 bytes that is pointed to by the node pointer right?
If this is true, then how do I free up all the memory that I have made with all the loops if I only have a pointer left pointing to the last malloc that happened?
Thanks!
Please allocate exactly the size you need: malloc(sizeof *node); -- if you move to a 64-bit platform that doubles the size of all your members, your old 96-byte structure might take 192 bytes in the new environment.
If you don't have any pointers to any of the struct Nodes you have created, then I don't think you should be allocating them with malloc(3) in the first place. malloc(3) is best if your application requires the data to persist outside the calling scope of the current function. I expect that you could re-write your function like this:
struct Node node;
while(...){
//do stuff with node
}
or
while(...){
struct Node node;
//do stuff with node
}
depending if you want access to the last node (the first version) or not (the second version).
Of course, if you actually need those structures outside this piece of code, then you need to store references to them somewhere. Add them to a global list keeping track of struct Node objects, or add each one to the next pointer of the previous struct Node, or add each one to a corresponding struct User that refers to them, whatever is best for your application.
If you set node = NULL before the loop and then use free(node) before node = malloc(100) you should be OK. You will also need to do a free(node) after the loop exits. But then again, it all depends on what "//do stuff with node" actually does. As others have pointed out, malloc(100) is not a good idea. What I would use is malloc(sizeof(*node)). That way, if the type of node changes, you don't have to change the malloc line.
If you don't need the malloc'ed space at the end of one iteration anymore, you should free it right away.
To keep track of the allocated nodes you could save them in a dynamically growing list:
#include <stdlib.h>
int main() {
int i;
void *node;
int prt_len = 0;
void **ptrs = NULL;
for (i = 0; i < 10; i++) {
node = malloc(100);
ptrs = realloc(ptrs, sizeof(void*) * ++prt_len);
ptrs[prt_len-1] = node;
/* code */
}
for (i = 0; i < prt_len; i++) {
free(ptrs[i]);
}
free(ptrs);
return 0;
}
Note: You should probably re-think your algorithm if you need to employ such methods!
Otherwise see sarnold's answer.
then how do I free up all the memory that I have made with all the loops if I only have a pointer left pointing to the last malloc that happened?
You can't. You just created a giant memory leak.
You have to keep track of every chunk of memory you malloc() and free() it when you're done using it.
You can not. You need to store all the pointer to free the memory. if you are saving those pointer somewhere then only you can free the memory.
I have a following sturcture for creating linked list, how can I free the allocated memeory?
typedef struct linked_list {
struct linkedl_ist *number;
POINTER house;
} list;
typedef list *LIST;
typedef void pointer
i have following list
LIST l1;
l1 = some_function(pointer);
These l1 is constructed using some variables. This is a linked list data structure as i mentioned. How can I free the memory allocated for l1?
[EDIT]
l1 holds a memory of 8 byte.
l1 doesn't need to be freed. It's on the stack. Return from the function you're in and it will automatically go away. The way to free what l1 points to is the same as the way to free the rest of the elements of the list: walk the list (using ->number) and free each element as you go.
LIST node = l1;
LIST next;
while (node != NULL)
{
next = node->number;
free(node);
node = next;
}
You have to free the memory pointers individually. There's not really a magic bullet here, you have to loop over the linked list and free the pointers for each node, then if your linked list itself is dynamically allocated, you have to free that.
It's important to free things in the correct order so you don't end up with dangling pointers. In other words, if you have pointer p which points to another pointer p2, you need to be sure to free p2 and then p. You don't want to free p before you free p2, because when you try to free p2 you are going through a dangling pointer to do it (e.g. free(p->p2) but p is already freed).
I think that you should free each element of your list manually, starting from l1, then l1->number etc.