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);
}
Related
Suppose I have a struct that looks like this:
typedef struct node{
char **word_ptrs;
int value;
struct node *next;
} Node;
and I have dynamically allocated spaces for the linked list, as well as the word_ptrs within this struct.
For example:
Node *head = malloc(sizeof(Node)); // not important, what I care is not this node.
head->word_ptrs = malloc(10 * sizeof(Node)); // I care about this.
My question is: I know how to free the linked list, but I feel confused when I try to free the dynamically allocated array. When I try to free the array above, should I just directly free the entire array? Or I should go to free every single char * within that array?
Thanks.
You should only pass to free what was returned from malloc.
In this case, you make one allocation for an array of char *, so you do a single free to clean it up. Also, the amount of space you're allocating is 10 * sizeof(Node), but it should be 10 * sizeof(char *).
That depends on where those pointers came from, and who owns them.
If they were dynamically allocated and the node owns them, then you should free them before freeing the array.
If they were dynamically allocated but owned elsewhere, their respective owners should free them later.
If they were not dynamically allocated, you mustn't free them at all.
If you have a combination of the three, you're in trouble.
You should also allocate it with sizeof(char*), or sizeof(*head->word_ptrs), not sizeof(Node).
Although, if the size is always ten, you might as well use an array:
typedef struct node{
char *word_ptrs[10];
int value;
struct node *next;
} Node;
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 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.
Im trying to create a linked list in c. The twist is that I want to allocate the memory for the list so that all the nodes are consecutively stored in memory.
Maybe an array structure is the way to go.
Any ideas?
The obvious way would be to allocate a number of nodes in a block, then link them together into a free list. When you need to add a node to your linked list, you'll grab the one from the head of your free list. When you want to delete a node, you link it back onto the free list:
struct node {
struct node *next;
// other data here.
};
node *free_list;
#define block_size 1024
void initialize() {
free_list = malloc(block_size * sizeof(struct node));
for (i=0; i<block_size-1; i++)
free_list[i].next = &free_list[i+1];
free_list[block_size-1].next = NULL;
}
struct node *alloc_node() {
struct node *ret;
if (free_list == NULL)
return NULL;
ret = free_list;
free_list = free_list->next;
return ret;
}
void free_node(struct node *n) {
n->next = free_list;
free_list = n;
}
If you're looking at a linked list, don't worry about where in memory they are. That's what the pointers on the nodes are for.
If you want them sequential, allocate an array.
Yes, use an array. More interesting is why you want this. If your program requires this to work, then you'll need to make sure your array is big enough to store all the nodes that might be allocated. If not, you can allocate batches of nodes.
FYI. I've seen this strategy used in the past on the assumption that sequentially allocated nodes would result in fewer cache misses when searching the list. In the system of interest, that didn't actually give much a performance improvement. [ Not enough profiling of course!.]
You could do something like this
struct node
{
int data;
struct node *next;
};
struct node linkedlist[50];
This would allocate space for linked list structure in contiguous locations.
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.