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.
Related
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.
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.
consider the following structures:
struct intNode
{
int num;
intNode* pNext;
};
struct list
{
intNode* first;
intNode* last;
int size;
};
suppose I allocated memory for the list. If I call free(lst) will it also free the memory allocated to the intNode first and last? and what about their own pNext? Intuitively I feel like I need to recursively free the nested memory blocks from the inside out.
You need to free them all individually, but usually for linked lists this is done iteratively, not recursively:
void DeleteList(struct intNode *pHead)
{
struct intNode *pCur=pHead, *pDel=NULL;
while(pCur != NULL)
{
pDel = pCur;
pCur = pCur->pNext;
free(pDel);
}
}
If you only frees memory of list element (when you have nodes), you cause a memory leak. In memory, the list looks like this:
[list caption]...other data...[node]...other data...[node]...[last node]
^(It is not always first!)
So, nodes aren't one uninterrupted memory area and they are not in contact with the caption. In these elements you have only address of next node, therefore you must free them memory of each element separately. If you do it only with the caption, the nodes remain in the memory. Furthermore you'll lose the address of first node, thereby you'll lose all addresses of all elements! In this case, you will not be able to get to the nodes or free their memory.
In response to your question, yes, you should do more. Freeing "parent's" memory isn't enough. In general, you should use free as much times as you use malloc or calloc. In this case it is simple. I just need to get the address of the first node and sequentially purified memory. Do not forget to keep the address of the next node (in a variable) before removing recent.
I have a simple Linked List node as follows
typedef struct node {
void *data;
struct ListElement *next;
} node;
Also I have a node create and delete function as follows:
void createNode(void *data){
node *n = malloc(sizeof(node));
//assign data to data and initialize pointer to NULL
}
void deleteNode(List *list, Node *node){
//Take care of the next pointer
free(node);
}
When I free the node, do I have to delete the members of the struct (data and next pointer) as well? Since I am not using malloc specifically for the members, but only for the entire struct? If so then how do I do it? Will all the members of the node be placed on the heap, and the stack will not be used at all?
The ultimate rule: you free() exactly the same number of times you malloc() (or calloc(), or...)
So:
I. If the data points to something allocated by these functions, then yes, you need to do so.
II. node->next is to be freed of course (assuming you are freeing the entire list), so you need to free it anyway, but only after you have taken care of the next element.
An iterative solution:
void free_list(Node *list)
{
while (list != NULL) {
Node *p = list->next;
// maybe:
// free(list->data);
free(list);
list = p;
}
}
A recursive solution:
void free_list(Node *list)
{
if (list->next != NULL) {
free_list(list->next);
}
// free(list->data);
free(list);
}
Usually, you will need to also free the data member, and you have to do that before freeing node,
free(node->data);
free(node);
but you don't need to free node->next, since either you want to keep the remainder of the list, or you free the entire list, and then freeing the next is done in the next iteration of the loop.
You must not free node->data if that doesn't point to allocated (with malloc or the like) memory, but that is a rare situation.
data is not a variable, it's a member of struct node. If you dynamically allocate struct node with a call to malloc(), you get a chunk of memory large enough to hold all the members of the struct. This obviously includes the storage for the data pointer, but not for the contents the pointer points to. Consequently, the storage for struct members must not be freed separately, it is enough to free the struct.
However, since data is itself a pointer, there is no telling where the memory it points to and whether this memory needs to be freed until we see how it is initialized.
I am juggling with two ways of free()'ing malloc()'ed memory in a linked list structure. Suppose I create a singly linked list with the following C code;
#include<stdio.h>
#include<stdlib.h>
struct node_type{
int data;
struct node_type *next;
struct node_type *prev;
}
typedef struct node_type node;
typedef struct node_type *list;
void main(void){
list head,node1,tail;
head=(list)malloc(sizeof(node));
tail=(list)malloc(sizeof(node));
node1=(list)malloc(sizeof(node));
head->next=node1;tail->prev=node1;
node1->prev=head;node1->next=tail;node1->data=1;
/*Method-1 for memory de-allocation*/
free(head->next->next);
free(head->next);
free(head);
/*OR*/
/*Method-2 for memory de-allocation*/
free(tail);
free(node1);
free(head);
/*OR*/
/*Method-3 for memory de-allocation*/
free(node1);
free(tail);
free(head);
}
Now, I have the following questions:
Q1) Which of the three methods of memory de-allocation shown in code above are correct/incorrect.
Q2) Is is necessary to follow any order in the free()'ing memory as used in Methods 1 and 2 for memory de-allocation OR randomly free()'ing memory is also fine?
All the methods you showed are correct, you should follow a specific order only when the pointer to an allocated memory exists only in another allocated memory, and you will lose it if you free the container first.
For example, for the allocation:
int ** ipp;
ipp = malloc(sizeof(int*));
*ipp = malloc(sizeof(int));
The correct free order will be:
free(*ipp);
free(ipp);
and not:
free(ipp);
free(*ipp); // *ipp is already invalid
All of these methods work fine. You can free memory blocks allocated by malloc in whatever order you like.
Just imagine for a moment that the order in which you allocated memory had to be reversed when you freed it. If that was so you could never insert or delete items from the middle of a list. Your only available dynamically allocated data structure would be a push-down stack.
Here's a simple way to free a linked list, starting at the head. (Note, this assumes "next" will be NULL if you're at the end of the list.)
node * it = head;
while( NULL != it ) {
node * tmp = it;
it = it->next;
free(tmp);
}