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.
Related
I am trying to understand the pointer logic behind prepending.
I declared a struct as follows:
typedef struct myList{
int info;
struct myList *link; //self referential structure;
} Node;
For memory allocation in the heap memory segment, I use the following function:
Node *getNode(){
return ((Node *)malloc(sizeof(Node)));
}
In the main function, I allocate memory for the first node, I assign its link to NULL and its value to 2.
Node *head = getNode();
head -> link = NULL;
head -> info = 2;
Then comes the prepend function:
void prepend(Node **headPointer, int value) {
Node *new_node;
new_node = getNode();
new_node -> info = value;
new_node -> link = *headPointer;
*headPointer = new_node;
}
I am using the following function call:
prepend(&head, 5)
As you can see, I'm using a pointer to a pointer. I store the address of head in headPointer. I create new_node and allocate memory to it. I assign its info field, then the link field gets the dereferenced headPointer, which is the value stored in head, which is in turn the address for the chunk of memory in the Heap segment.
So, I basically link new_node to head, right? Now comes the confusing part, for me. The dereferenced headPointer, which is head's pointed chunk of memory in the Heap segment, gets the value stored in new_node which is another address from the Heap segment, I guess. Then, both new_node and headPointer go out of scope. (?)
How does this all add up? Is there a simpler way to describe the situation or implement prepending?
Then, both new_node and headPointer go out of scope. (?)
At the end of the prepend() newnode goes out of scope but not the memory allocated since it is allocated on heap.If it were something like int a, then at the end of prepend(), a is gone out of scope and referencing a after that would be undefined behavior.Please read this and this to know about heap.
Also since you pass head of the list as pointer to pointer, when you change what the headPointer points to inside prepend(), it is reflected outside the function so you still have a pointer to the head of the list.
|2|-->NULL
^
|
head
After call to prepend()
1) |5|--> |2|-->NULL
^
|
head
2) |5|----> |2|--->NULL
^
|
head
Also remeber to have some way of accessing the heap allocated memory in order to deallocate it.If you don't have any means of pointing to a memory allocating on a heap, then you are left with a memory leak.
This is my function to add a new node using double pointer
void insertBefore(node_t **first)
{
node_t *new = NULL;
new = (node_t *) malloc(sizeof(node_t));
new->next = *first;
*first = new;
free(new);
}
If I use it once, everything seems to work fine. However, if I use it again, my linked-list is messed up. I have the output image below (same thing happened to my function to insert node to any position).
I tried to put some very specific part of the code, so if you suspect that I must have been doing something wrong at other parts, please tell me.
Any idea what did I do wrong?
The output image
Just remove free(new);. Since new and *first have same value, freeing new also frees *first.
Refined code:
void insertBefore(node_t **first)
{
node_t *new = malloc(sizeof(node_t)); //don't cast
if(!new)
{
fputs("Don't have enough memory", stderr);
return;
}
new -> next = *first;
*first = new;
}
It because you are freeing the memory.
free(new);
You are just assigning the value to first.
*first=new;
Now first and new will point to same memory position. Then you are freeing that memory. Remove the line free(new);.
You free the node you had just allocated; whenever you attempt to use it, undefined behavior will occur because *first becomes a Dangling Pointer. The address stored in the pointer is no longer valid after the function free() returns.
Your code needs many improvements
You don't need to initialize new to NULL; probably no problem as this would be optimized.
You don't need to cast malloc() or in general void * to any other pointer type.
You don't check that malloc() was successful; you should check that new is not being assigned NULL which would indicate an error.
You MUST NOT free() the newly allocated pointer; you should free() it when you don't need it anymore and not immediately after allocating it.
You really should improve your code formatting. It was completely unreadable in the original post.
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 have written a binary search tree, it works fine but I'm not sure whether my program frees all the memories.
here is my definition of the node of a tree
typedef struct node {
int val;
struct node *left, *right;
} nodeOfTree;
I write this function to output the result and free all the nodes, it seems that the answer is right but the memories are not freed.
void outputAndDestroyTree(nodeOfTree *root) {
if (!root) {return;}
outputAndDestroyTree(root->left);
printf("%d ", root->val);
outputAndDestroyTree(root->right);
free(root); // I free this pointer, but after doing that, I can still access this pointer in the main() function
}
Is that mean I can not free a piece of memories in the recursive function? Thank you ~~~~~
Update: Thank you all~
Your code seems okay, but freeing the allocated memory won't magically set it's reference pointer to NULL. Since you didn't set a new value to the pointer, the old address will remain there, untouched. Maybe you can even read from it without crashing, despite it being undefined behavior.
If you want it to be set to NULL after freeing the memory, then just do so. Call outputAndDestroyTree(root->left); then do root->left = NULL;.
I am relatively new to the idea of pointers and C, so I apologize if this is a really simple problem. I am trying to free a singly linked list from memory that is created. The singly list is created fine, but I am having trouble free it from memory, I get a segmentation fault. Any ideas where I am going wrong? I need to have separate methods for both freelist and freenode. Avail is a global pointer variable and is part of the code that I'm sure works. The problem exists in free list and I'm just not sure where.
void freelist(olnode **list) {
olnode *ptr = *list;
while (*list != NULL) {
ptr = *list
freenode(&ptr);
ptr = ptr->next;
}
}
void freenode(olnode **ptr) {
if(*ptr != NULL) {
(*ptr)->next = avail;
avail = *ptr;
*ptr = NULL:
}
}
Freenode sets the pointer passed to it to NULL. Afterwards freelist tries to dereference the pointer which is now null. That's where the program crashes.
Besides that, your program doesn't really free any data. It just changes the pointers pointing to the data to point to NULL. That means the memory will stay allocated and isn't available for new data. To mark the memory a pointer points to as no longer needed, you need to call the free() method from the standard library on the pointer which points to it. Setting the pointer to NULL afterwards is not needed, but a good practice to make sure that any subsequent try to access the free'ed memory location results in a predictable crash and not in totally unpredictable behavior.
You need to grab the next pointer from the node before freeing it.
Not this:
freenode(&ptr);
ptr = ptr->next;
but this:
olnode *next = ptr->next;
freenode(&ptr);
ptr = next;