Where to deallocate (free) - c

Studying a tutorial on linked lists in C. I've compiled this code and ran it through valgrind. It show's 4 allocations and 0 frees, which I understand. I need to know how to properly call free() to deallocate.
Code example: llist2.c
// linked list: inserting at the n'th position
#include "stdio.h"
#include "stdlib.h"
typedef struct Node
{
int data;
struct Node* next;
} Node;
Node* head;
void Insert(int data, int n)
{
Node* temp1 = malloc(sizeof(Node));
temp1->data = data;
temp1->next = NULL;
if(n==1) { // list is empty, set next to head, initially NULL.
temp1->next = head;
head = temp1;
return;
}
Node* temp2 = head;
for(int i = 0; i < n-2; i+=1) {
temp2 = temp2->next;
}
temp1->next = temp2->next;
temp2->next = temp1;
}
void Print() {
Node* temp = head;
while(temp != NULL) {
printf("%d ", temp->data);
temp = temp->next;
}
printf("\n");
}
int main (int argc, char *argv[])
{
head = NULL;
Insert(2,1);
Insert(3,2);
Insert(4,1);
Insert(5,2);
Print();
return 0;
}

You need to create a function to free your list.
void freelist(Node* head)
{
Node *next,*curr;
curr = head;
while (curr != NULL)
{
next = curr -> next;
free(curr);
curr = next;
}
}
You can call this in main at the end.
int main (int argc, char *argv[])
{
// Other code
freelist(head);
head = NULL;
return 0;
}

You should deallocate after finished using what is allocated. Follow the list and deallocate.
For example, you can call this function Deallocate() after calling Print().
void Deallocate() {
Node* temp = head;
while(temp != NULL) {
Node* next = temp->next;
free(temp);
temp = next;
}
head = NULL;
}
Note that you cannot do like this
void Deallocate_bad() {
Node* temp = head;
while(temp != NULL) {
free(temp);
temp = temp->next; /* undefined behavior */
}
head = NULL;
}
because you cannot access temp->next after deallocating temp.

Related

Circular linked list crashes when displayed

I'm trying to make a circular linked list. When I try to display the list after creating it, the program keeps on crashing. Here is my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node * next;
} node;
node * createList(int);
void display(node * head);
int main() {
struct node * head;
head = createList(5);
display(head);
}
node * createList(int n) {
int i = 0,data = 0;
struct node * head = NULL;
struct node * temp = NULL;
struct node * p = NULL;
for (i = 0; i < n; i++) {
temp = (node*)malloc(sizeof(node));
temp->data = data++;
temp->next = head;
if (head == NULL) {
head = temp;
} else {
p = head;
while (p->next != NULL) {
p = p->next;
}
p->next = temp;
}
}
return head;
}
void display(node * head) {
struct node * temp = head->next;
while (temp != head) {
printf("%d-> \t",temp->data);
temp = temp->next;
}
printf("\n");
}
What am I doing wrong?
You have set every temp's next to head in temp->next = head; but did it too early (the first is just NULL). Then you tested p->next against NULL in while (p->next != NULL) { but you should have tested against head. Alternatively, you can continue to test against NULL but then you need to initialize temp->next to NULL and assign head to temp->next only after the for loop.
Your display code started from the second link.
Here is a fixed code using the first option in 1. above:
for (i = 0; i < n; i++) {
temp = (node*)malloc(sizeof(node));
temp->data = data++;
if (head == NULL) {
head = temp;
} else {
p = head;
while (p->next != head) {
p = p->next;
}
p->next = temp;
}
temp->next = head;
}
Here is a fixed code using the alternative option in 1. above. You still need to initialize temp->next to NULL since malloc() does not initialize.
for (i = 0; i < n; i++) {
temp = (node*)malloc(sizeof(node));
temp->data = data++;
temp->next = NULL;
if (head == NULL) {
head = temp;
} else {
p = head;
while (p->next != NULL) {
p = p->next;
}
p->next = temp;
}
}
if (temp != NULL) {
temp->next = head;
}
But in reality, there is no need to "walk" from the head on every creation. You can simply keep the previous and link it to the next:
for (i = 0; i < n; i++) {
temp = (node*)malloc(sizeof(node));
temp->data = data++;
if (head == NULL) {
head = p = temp;
} else {
p = p->next = temp;
}
}
if (temp != NULL) {
temp->next = head;
}
Here is a fix for the display():
void display(node * head) {
struct node * temp = head;
if (temp != NULL) {
do {
printf("%d-> \t",temp->data);
temp = temp->next;
} while (temp != head);
}
printf("\n");
}
The problem is on the first node you initialize:
struct node *head = NULL;
...
for (i = 0; i < n; i++) {
...
temp->next = head;
So tmp->next == NULL on the first iteration leaving head->next == NULL. That will not work for a circular list. When you attempt to insert the 2nd node:
p = head;
while (p->next != NULL) {
What was head->next again?? (oh, NULL) Dereferencing a NULL pointer (BOOM Segfault!)
Do your circular list correctly. On insertion of the first node set:
if (head == NULL) {
head = temp;
head->next = temp; /* you must set head->next to temp */
} ...
So on the insertion of the remaining nodes you simply need:
} else {
p = head;
while (p->next != head) { /* iterate to last node */
p = p->next;
}
p->next = temp; /* now set p->next = temp */
}
Now, you handle your display() function the same way, e.g.
void display (node *head)
{
if (!head) { /* validate list not empty */
puts ("(list-empty)");
return;
}
struct node *temp = head;
do { /* same loop problem fixed in display() */
printf ("%d-> \t", temp->data);
temp = temp->next;
} while (temp != head);
putchar ('\n');
}
If you make the changes, then you can test your list with:
int main (void) {
struct node *head, *tmp;
head = createList(5);
display (head);
puts ("\niterate from mid-list");
tmp = head;
tmp = tmp->next;
tmp = tmp->next;
display (tmp);
}
Example Use/Output
$ ./bin/lls_circular_fix
0-> 1-> 2-> 3-> 4->
iterate from mid-list
2-> 3-> 4-> 0-> 1->
Lastly, you are not multiplying the type node by head in struct node * head = NULL; Write it as struct node *head = NULL; (the same for all your function declarations as well) Much more readable.
When you go to delete a note from the list, you must create a special case for both head and tail (the last node). In this sense, the singly-linked list takes a bit more effort than a doubly-linked list due to not having a prev node pointer to track the prior node.
Look things over and let me know if you have questions.
A full example would be:
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next;
} node;
node *createList (int);
void display (node *head);
int main (void) {
struct node *head, *tmp;
head = createList(5);
display (head);
puts ("\niterate from mid-list");
tmp = head;
tmp = tmp->next;
tmp = tmp->next;
display (tmp);
}
node *createList (int n)
{
int i = 0,data = 0;
struct node *head = NULL;
struct node *temp = NULL;
struct node *p = NULL;
for (i = 0; i < n; i++) {
if (!(temp = malloc (sizeof *temp))) {
perror ("malloc-temp");
return NULL;
}
temp->data = data++;
temp->next = head; /* head is NULL on 1st node insertion */
if (head == NULL) {
head = temp;
head->next = temp; /* you must set head->next to temp */
} else {
p = head;
while (p->next != head) { /* iterate to last node */
p = p->next;
}
p->next = temp; /* now set p->next = temp */
}
}
return head;
}
void display (node *head)
{
if (!head) { /* validate list not empty */
puts ("(list-empty)");
return;
}
struct node *temp = head;
do { /* same loop problem fixed in display() */
printf ("%d-> \t", temp->data);
temp = temp->next;
} while (temp != head);
putchar ('\n');
}

getting segmentation error (core dumped) in linked list

I have looked at my code several times but couldn't find the problem. please tell me what I need to replace to get my code working.
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
struct node
{
int data;
struct node *next;
};
struct node *head;
void insert(int x)
{
struct node *temp=(struct node *)malloc(sizeof(struct node));
temp->data = x;
temp->next = NULL;
if (head == NULL)
{
temp->next = head;
head = temp;
return;
}
struct node *temp1 = head;
while(temp1 != NULL)
{
temp1 = temp1->next;
}
temp1->next = temp;
}
void display()
{
struct node *temp = head;
if (head == NULL)
{
printf("list is empty");
return;
}
else{
while(temp!=NULL)
{
printf("%d ", temp->data);
temp = temp->next;
}
}
}
int main()
{
head = NULL;
insert(3);
insert(5);
insert(6);
display();
}
The problem is in this code:
struct node *temp1=head;
while(temp1!=NULL)
{
temp1=temp1->next;
}
temp1->next=temp;
... the while loop won't end until temp1 is NULL, so after the loop ends, it is guaranteed that temp1 is a NULL pointer ... and then you dereference that NULL pointer (via temp1->next), which causes a crash. Probably what you want to do instead is while(temp1->next != NULL) {...}
while(temp1!=NULL)
{
temp1=temp1->next;
}
temp1->next=temp;
The only way out of this loop is for temp1 to be NULL. Then the next line attempts to used temp1 as a pointer. This is likely causing your issue. You need to instead check if the next is NULL and break leaving temp1 as the last in the list not it's next.
Pro tip for linked lists like this, they are a lot easier to modify with double pointers. Example code:
void append(struct node **list, int a) {
// skip to the end of the list:
while (*list != NULL) {
list = &(*list)->next;
}
*list = malloc(sizeof(struct node));
(*list)->data = a;
(*list)->next = NULL;
}
void display(struct node *list) {
while (list) {
printf("%d\n", list->data);
list = list->next;
}
}
void remove(struct node **list, int index) {
while (*list) {
if (--index == 0) {
struct node *temp = *list;
*list = temp->next;
free(temp);
break;
}
}
}
int main() {
struct list *mylist;
append(&mylist, 3);
append(&mylist, 4);
append(&mylist, 5);
display(mylist); // prints 3 4 5
remove(&mylist, 1);
display(mylist); // prints 3 5
remove(&mylist, 0);
remove(&mylist, 0);
// mylist is NULL again, all memory free'd
}
Note that this code needs no special cases for "is the list empty?", which makes it less complex than yours.

Linked List using recursion - Unexpected Output

I found this on Internet to reverse a list using recursion and applied it in codeblocks but the output only reverse prints last two Insert call from main function. It skips the first three Insert calls. Why? I did search for this problem here but I failed to understand them as I'm a beginner. Kindly help
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node* next;
};
struct Node * head;
struct Node* Insert (struct Node* head, int data)
{
struct Node* temp = (struct Node*)malloc(sizeof(struct Node));
temp->data = data;
temp->next = NULL;
if(head == NULL)
{
head = temp;
return;
}
struct Node* temp2 = head;
while(temp2->next != NULL)
{
temp2 = temp2->next;
}
temp2->next = temp;
}
void reversePrint(struct Node* head)
{
if(head == NULL)
{
printf("\n");
return;
}
reversePrint(head->next);
printf(" %d ", head->data);
return;
}
int main()
{
struct Node* head = NULL;
head = Insert(head,2);
head = Insert(head,7);
head = Insert(head,3);
head = Insert(head,1);
head = Insert(head,4);
reversePrint(head);
return 0;
}
O/P : 4 1
NOTES:
Don't cast the return of value of malloc
You declared two *head and confused yourself
No need to pass pointer to function and return pointer when you have head declared as global. Which is not a good idea but I followed your code.
Code:
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node* next;
};
struct Node * head;
void Insert (int data)
{
struct Node* temp = malloc(sizeof(struct Node));
temp->data = data;
temp->next = NULL;
if(head == NULL)
{
head = temp;
return;
}
struct Node* temp2 = head;
while(temp2->next != NULL)
{
temp2 = temp2->next;
}
temp2->next = temp;
}
void reversePrint(struct Node* head)
{
if(head == NULL)
{
printf("\n");
return;
}
reversePrint(head->next);
printf(" %d ", head->data);
return;
}
int main()
{
Insert(2);
Insert(7);
Insert(3);
Insert(1);
Insert(4);
reversePrint(head);
return 0;
}
OUTPUT:
4 1 3 7 2

struct undeclared (first use in this function)

I'm very new to programming and I started to learn C. Now I just cant understand why my node structure is not visible to my functions.
I try to get some help on http://www.cprogramming.com/tutorial/c/lesson7.html
but with no luck in using code blocks 13.12
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct ptr * next;
};
struct node* head;
void Insert(int x)
{
struct node *temp;
temp = (node*)malloc(sizeof(struct node));
if(head == NULL)
head = temp;
temp->data = x;
temp->data = x;
temp->next = NULL;
struct node* temp1 = head;
while(temp1-> != NULL;) {
temp1 = temp1->next;
}
temp1->next = temp;
}
void print() {
struct node* temp = head;
while(temp != NULL) {
printf("the data is %d", temp->data);
temp = temp->next;
}
}
int main ()
{
head = NULL;
int a,c;
printf("How many numbers ? : \n");
scanf("%d",&a);
for(i = 0; i<a; i++); {
printf("Enter a number:\n");
scanf("%d",&c);
Insert(c);
print();
}
}
There are quite a few lets go one by one
number 1
struct node {
int data;
struct node *next; // chagnge ptr -> node
};
number 2
struct node *temp;
temp = malloc(sizeof(struct node)); // struct node casting
number 3
while(temp1->next != NULL) { // remove semi colum and put a next
temp1 = temp1->next;
}
number 4
int i; // for while loop
for(i = 0; i<a; i++) {
Now hopefully it compiles well, check runtime errors ( if any )
and yes
return 0; // just before main
you are building an infinite loop with your first element:
temp = (struct node*)malloc(sizeof(struct node));
if(head == NULL)
head = temp;
temp->data = x;
temp->next = NULL;
struct node* temp1 = head;
while(temp1->next != NULL) { // nothing to do
temp1 = temp1->next;
}
temp1->next = temp; //temp is head and temp1 is head, so head->next points to head
you should do something like
if (head == NULL) {
//fill head and leave
} else {
//traverse to the last element and concatenate the new element
}

inline implementation and function calling showing two different behavior in C?

I have been trying to implement the delete function for singly linked list.
My implementation is as follow.
typedef struct singly_linked_list{
int data;
struct singly_linked_list *next;
}sll;
Function to delete first node is as follow:
void delete_node_from_front(sll ** head){
sll ** temp;
*temp = *head;
(*head) = (*head)->next;
(*temp)->next = NULL;
free_node(temp);
}
Another function from where I am calling this function:
void delete_node_from_given_pos(sll ** head, int pos){
int i = 1;
sll * temp;
sll * prev;
temp = *head;
prev = *head;
if(pos == 1){
delete_node_from_front(head);
}
else{
while(temp != NULL && i < pos){
i++;
prev = temp;
temp = temp->next;
}
if(temp != NULL){
prev->next = temp->next;
temp->next = NULL;
free_node(&temp);
}
else{
printf("Node with given position is not present");
}
}
}
This implementation is giving me segmentation fault.
But If I replace the function call delete_node_from_front() in the imlementation of delete_node_from_given_pos() by the below code
(*head) = (*head)->next;
temp->next = NULL;
free_node(&temp);
program runs perfectly. The way I am calling the fucntion:
sll * head;
head = NULL;
int arr[_SIZE]=_ELEMENT;
create_list(&head, arr, _SIZE);
delete_node_from_given_pos(&head, 1);
print_list(head);
Implementation of print_list function
void print_list(sll * head){
int i = 0;
while(head != NULL){
printf("%d ", head->data);
head = head->next;
}
printf("\n");
}
implementation of free_node function:
void free_node(sll ** head){
free(*head);
}
What could be the possible reason for this behavior?

Resources