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.
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 have a linked list struct, i want to pass one node (another struct) pointer to a function (the node is part of the linked list, but i'm passing the node seperately to a deleter function
I want it to copy the next node data into itself (overriding its data), and to delete the next node, thus deleting itself (this part is working)..
I made it check whether the passed node is the last node in the list, and if so, to delete itself.
I don't know how to delete structs from the stack (i know i can malloc() and free() it using the heap memory).
#include <stdlib.h>
#include <stdio.h>
typedef struct {
int data;
struct node * next;
}node;
typedef struct {
struct node * head;
}linked_list;
void print_list(linked_list * list) {
node *current = list->head;
while (current) {
printf("Current node has %d\n",current->data);
current = current->next;
}
}
void delete_node(node * n) {
node * next = n->next;
if (next) {
n->data = next->data;
n->next = next->next;
}
else {
*n = NULL; /*This of course won't compile because assigning void* (null) to node variable
but if i make n point to NULL, nothing will happen because i'm inside a function
and the pointer is duplicated (the passed pointer will still work) */
}
}
void main(){
node first;
node second;
first.data = 1;
first.next = &second;
second.data = 2;
second.next = NULL;
linked_list l;
l.head = &first;
print_list(&l);
delete_node(&second);
print_list(&l);
}
As others have said, you can't.
If you want to be able to store both allocated (by malloc) and non-allocated (static or automatic) storage objects in your list and have a "delete" function that removes objects from the list and frees them, you need to store as part of each list member a flag indicating whether it's in allocated storage or not, and only free the ones which are.
Also note that you'll be in big trouble if the lifetime of the structure with automatic storage ends before you remove it from the list! If dealing with this is confusing at all for you, then you would probably be better-off just using allocated storage (malloc) for all list members.
You can't :)
On most computer architectures, local variables are either allocated directly on a CPU register or on the stack. For local variables allocated on the stack, the top of the stack (the same stack that is used to hold the return addresses of function calls) is manipulated to make space for them when a function enters, and it is restored to "release" the memory when the function exits. All this stack management is handled automatically by the compiler.
You can use the 'free' operator for freeing / deleting a malloc assigned object in the memory. For that, in your code you can write :
free(n);
Here's the task. It is given a linked list, free all the memory and set head to NULL.
This is my function:
void free_list(struct Node *node)
{
while (node)
{
free(node);
node=node->next;
}
}
It outputs no error, just wont do anything. And another thing, how to check if the memory was freed ?
Hints at what's going wrong rather than sample code since this is homework...
You can't reliably access node after freeing it. Store the value of node->next before freeing.
You're passing the Node pointer by value. If you want to NULL the caller's pointer, use a pointer to a pointer instead.
There is no portable way to check the memory was freed, but you could investigate tools like valgrind if you want to check that no memory has been leaked when your program exits.
Note that you can't check the contents of memory locations to reassure yourself that the memory has been freed. Calling free merely passes ownership of the memory back to the system; it may get reallocated (and its values updated) at any point in future.
You should get the next node before freeing the current one
If you want to assign to the head, you need to pass its address to the function.
void free_list(struct Node **head)
{
struct node *nnode, *cnode;
cnode = *head;
while (cnode)
{
nnode = cnode->next;
free(cnode);
cnode = nnode;
}
*head = NULL;
}
call it like this..,,
free_list(&head);
EDIT:
You are accessing the same node node=node->next; after freeing it, You must have to store next pointer before freeing the node.
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);
}
I have link list whose node structure is given below
struct node
{
char *p;
struct node *next;
}*start;
Now we char *p is pointer to memory location which allocated by malloc call.Similarly the whole is also allocated using malloc. Now would like to free the space occupied by both the malloc call ,something like this below
main()
{
struct node *tmp;
tmp=malloc(sizeof(struct node));
tmp->next=NULL;
tmp->p=malloc(2*sizeof(int));
free(tmp->p);
free(tmp);
}
Is it the right way to free memory or something is required here?
This is the right way but don't forget to assign pointers to NULL after using free otherwise the pointers will become dangling pointers.
Use them like this -
free(tmp->p);
tmp->p = NULL;
you are freeing correctly, although normally you would have a pointer to the first node then loop through the list by following the pointers. e.g.
struct node *first;
... list created, first pointing to first in list, where last next is == NULL ...
while (first != NULL)
{
struct node* next = first->next;
free( first->p );
free( first );
first = next;
}
btw why do you declare p as char* but allocate ints? typo?