Segmentation fault while doing malloc for a struct pointer - c

I trying to write basic Linked list code. I have two functions to add data to beginning of list and end of the list. Function to add data in the beginning works fine every time.
I am facing segmentation fault in insert_end function always.
I am getting the error while trying to access temp1 pointer to structure after doing malloc to it. But this is the same exact thing I am doing even in the insert_first function, but works every time. I tried googling it and tried in forums, no answer. Please help.
This link is my exact kinda problem.. but i dont understand the solution fully
Segmentation fault in C with malloc
I am getting error particularly on this block
struct node *temp1,*trav;
temp1 = (struct node *)malloc(sizeof(struct node));
trav = (struct node *)malloc(sizeof(struct node));
if (temp1 != NULL) { //******************Segmentation fault at this line**********
temp1->data = input;
}
#include<stdio.h>
#include<stdlib.h>
//*******Structure to hold linked list*********//
struct node {
int data;
struct node *next;
}*head,*temp;
//***********Function to Display everything**********//
void display(struct node *head) {
struct node *trav;
trav= (struct node *)malloc(sizeof(struct node));
printf("Entering into Display\n");
if (head == NULL) {
printf("Oh My God, the list is empty\n");
}
else {
trav = head;
while (trav != NULL) {
printf("Value stored in [%p] is [%d]\n",trav,trav->data);
trav = trav->next;
}
}
}
//***********Function to Insert at beginning*********//
struct node *insert_first(struct node *head,int input) {
temp = (struct node *)malloc(sizeof(struct node));
temp->data = input;
printf("\nEntering insert first");
if (head == NULL) {
head = temp;
head->next = NULL;
}
else {
temp->next = head;
head = temp;
}
return head;
}
//**************Function to Insert at End******************//
struct node *insert_last(struct node *head,int input) {
struct node *temp1,*trav;
temp1 = (struct node *)malloc(sizeof(struct node));
trav = (struct node *)malloc(sizeof(struct node));
if (temp1 != NULL) {
temp1->data = input;
}
else {
printf("empty");
}
printf("\nEntering insert last");
if (head == NULL) {
head = temp1;
head->next = NULL;
}
else {
trav = head;
while (trav != NULL) {
trav = trav->next;
}
trav->next = temp1;
}
return head;
}
//*************Main Fucntion***********//
int main() {
int choice,value;
head = NULL;
while(1) {
printf("\n******Please Enter your choice****\n1. To insert at beginning\n2. To insert at End\n3. To Insert middle\n4. To delete\n5. To display\n0. To Exit\n");
scanf("%d",&choice);
switch(choice){
case 1:
printf("Please Enter the value to be added\n");
scanf("%d",&value);
head = insert_first(head,value);
break;
case 2:
printf("Please Enter the value to be added\n");
scanf("%d",&value);
head = insert_last(head,value);
break;
case 5:
display(head);
break;
case 0:
return 0;
default:
printf("Thats a wrong choice\n");
break;
}
}
}

This is the problematic block.
else {
trav = head;
while (trav != NULL) {
trav = trav->next;
}
trav->next = temp1;
When you come out of the while loop trav is NULL. That makes the line
trav->next = temp1;
fail with segmentation violation.
Change that block to:
else {
trav = head;
while (trav->next != NULL) {
trav = trav->next;
}
trav->next = temp1;

Related

Segmentation fault in linked list program (c language)

I'm trying to write a code for linked lists using c++. Insert at begin and Insert at end are not working for some reason. Here is the code.
`
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
void insertAtBeginning(int );
void insertAtEnd(int );
void printLL();
struct Node
{
int data;
struct Node *link;
};
struct Node *head;
int main()
{
struct Node *temp, *newnode;
int ch=1, i=1, info;
head = NULL;
while(ch)
{
printf("Enter data: ");
scanf("%d", &info);
newnode = (struct Node *)malloc(sizeof(struct Node));
newnode->data = info;
newnode->link = NULL;
if(head == NULL)
{
head = newnode;
temp = newnode;
}
else
{
temp ->link = newnode;
temp = newnode;
}
printf("You wish to continue? (press 0 to terminate)\n");
scanf("%d",&ch);
if(!ch)
{
break;
}
}
temp = head;
while(temp!=NULL)
{
printf("%d -> ",temp->data);
temp = temp->link;
}
printf("\n");
insertAtBeginning(50);
insertAtEnd(150);
//printLL();
}
void insertAtBeginning(int info)
{
struct Node *newnode;
newnode->data = info;
printf("\n%d\n", newnode ->data);
newnode->link = head;
head = newnode;
}
void insertAtEnd(int info)
{
struct Node *temp, *newnode;
newnode->link = NULL;
newnode->data = info;
temp = head;
while(temp!=NULL)
{
temp = temp->link;
}
temp->link = newnode;
printf("\n%d\n", newnode -> data);
}
void printLL()
{
struct Node *temp;
temp = head;
while(temp!=NULL)
{
printf("%d -> ",temp->data);
temp = temp->link;
}
}
`
The problem is somewhere around newnode->data = info in the functions.
I created two functions, one to insert an element at beginning and one to insert an element at end. In both of them, i've created a newnode. The problem is I cannot insert data into those nodes.
When you want to append a new node to the end of a linked list, you must find your last node (a node which its link is NULL, not itself). Also, it is better to use meaningful variable name (temp is too general name). You also forgot to malloc new nodes in insertAtBeginning and insertAtEnd functions. I've fixed these issues in the following code
#include<stdio.h>
#include<stdlib.h>
void insertAtBeginning(int );
void insertAtEnd(int );
void printLL();
struct Node
{
int data;
struct Node *link;
};
struct Node *head = NULL;
int main()
{
struct Node *it, *newnode, *tail;
int ch=1, i=1, info;
while(ch){
printf("Enter data: ");
scanf("%d", &info);
newnode = malloc(sizeof(struct Node));
newnode->data = info;
newnode->link = NULL;
if (head == NULL) {
head = newnode;
tail = newnode;
} else {
tail->link = newnode;
tail = newnode;
}
printf("You wish to continue? (press 0 to terminate, else to continue)\n");
scanf("%d",&ch);
if(ch == 0) {
break;
}
}
it = head;
while(it != NULL) {
printf("%d -> ",it->data);
it = it->link;
}
printf("\n");
insertAtBeginning(50);
insertAtEnd(150);
}
void insertAtBeginning(int info)
{
struct Node *newnode;
newnode = malloc(sizeof(struct Node));
newnode->data = info;
printf("\n%d\n", newnode->data);
newnode->link = head;
head = newnode;
}
void insertAtEnd(int info)
{
struct Node *it, *newnode;
newnode = malloc(sizeof(struct Node));
newnode->link = NULL;
newnode->data = info;
it = head;
while(it->link != NULL)
{
it = it->link;
}
it->link = newnode;
printf("\n%d\n", newnode->data);
}
void printLL()
{
struct Node *it;
it = head;
while(it!=NULL)
{
printf("%d -> ",it->data);
it = it->link;
}
}
You're treating your uninitialized stack variable (struct Node *newnode) as a pointer to a struct Node and trying to update its fields:
struct Node *newnode;
newnode->data = info;
This doesn't work because the value of newnode is whatever garbage was on the stack beforehand, and trying to deref it (*newnode) will likely give a seg fault since you're trying to read from some unknown memory address.
Notice how inside main, you assign a result from malloc to newnode, this means you know that (given that malloc didn't return NULL), the pointer is valid, and you're free to use the memory it points to.

How to insert a value into a doubly linked list using C

I am just trying to insert a value to a sorted doubly linked list in C.
When I print it out using the following it never shows the newly created node. I created a new node and then set the values and then update the prev and next pointers for the new node and the node that was in front of it. I am sure it has something to do with pass by reference and would like to understand why?
struct NodeType {
int data;
struct NodeType * prev;
struct NodeType * next;
}*head, *last;
void insert_double(int key);
void displayList();
void find_node(int key);
int main()
{
head = NULL;
last = NULL;
/* Create a list with one as value and set as head */
head = (struct NodeType *)malloc(sizeof(struct NodeType));
head->data = 3;
head->prev = NULL;
head->next = NULL;
last = head;
int value=1;
insert_double(value);
printf("0\n");
displayList();
printf("1\n");
value=2;
printf("2\n");
find_node(value);
printf("3\n");
displayList();
return 0;
}
void displayList()
{
struct NodeType * temp;
int n = 1;
if(head == NULL)
{
printf("List is empty.\n");
}
else
{
temp = head;
printf("DATA IN THE LIST:\n");
while(temp != NULL)
{
printf("DATA of %d node = %d\n", n, temp->data);
n++;
/* Move the current pointer to next node */
temp = temp->next;
}
}
}
void find_node(int key)
{
struct NodeType * temp;
struct NodeType * newnode;
newnode->data=key;
if(head == NULL){
printf("No nodes");
}
else{
temp=head;
while(temp!=NULL)
{
if((temp->data)< key){
newnode->prev=temp->prev;
newnode->next=temp;
temp->prev=newnode;
break;
}
else{
temp=temp->next;
}
}
}
}
void insert_double(int key)
{
struct NodeType * newnode;
if(head == NULL)
{
printf("Empty!\n");
}
else
{
newnode = (struct NodeType *)malloc(sizeof(struct NodeType));
newnode->data = key;
newnode->next = head; // Point to next node which is currently head
newnode->prev = NULL; // Previous node of first node is NULL
/* Link previous address field of head with newnode */
head->prev = newnode;
/* Make the new node as head node */
head = newnode;
}
}
Your code is basically correct. You are just missing two important edge cases when dealing with linked list. First is when you are using find_node to insert some value, but it's gonna be add in the beginning in the list. In this case your newly created node becomes a new head of a list so you have to update a head variable. The second edge case is kind of opposite, it happens when you are inserting the new node to the end of the list. Then it becomes an end of a list so you need to update tail.
Missing those two edge cases happens a lot when first working with the linked lists, so don't worry. I think pretty much everybody who worked with linked list made these mistakes in the beginning of his journey.
Moreover you are using the uninitialized pointer to the NodeType structure in find_node:
struct NodeType * newnode;
it should be:
struct NodeType * newnode = (struct NodeType *)malloc(sizeof(struct NodeType));
Thanks to both of you. Here is the solution I came up based on both of your input:
void insert_sorted_node(int key){
struct NodeType * temp = (struct NodeType *)malloc(sizeof(struct NodeType));
struct NodeType * newnode = (struct NodeType *)malloc(sizeof(struct NodeType));
newnode->data=key;
/* no nodes at all*/
/* insert_sorted_node(value) can't start empty list, need to fix */
if(head == NULL){
printf("head =null");
temp = head;
head->data=key;
head->prev=NULL;
head->next=NULL;
last = head;
}
else{
temp=head;
while(temp!=NULL)
{
printf("\n\ndata = %d\nkey = %d\n", temp->data, key);
/* key is new head
1) check if key < head->data
*/
if(key<head->data)
{
printf("\nnew head\n");
newnode->prev = head->prev;
newnode->next = temp;
temp->prev = newnode;
head = newnode;
break;
}
/* key is tail
if temp->next = NULL
*/
else if(temp->next == NULL)
{
printf("\ntail\n");
newnode->prev = temp;
newnode->next = NULL;
temp->next = newnode;
last = newnode;
break;
}
/* key is middle head
if key > temp->data and key< temp->next->data
*/
else if((key>temp->data)&&(key<temp->next->data))
{
printf("\nmiddle\n");
newnode->prev=temp;
newnode->next=temp->next;
temp->next=newnode;
temp->next->prev=newnode;
break;
}
else{
printf("next\n");
temp=temp->next;
}
}
}
}
Your insertion function works fine, as does displayList.
However, the program has undefined behavior in the find_node function:
void find_node(int key)
{
struct NodeType * temp;
struct NodeType * newnode;
newnode->data=key; //<-- BOOM! (writing to uninitialized pointer)
if(head == NULL){
printf("No nodes");
}
else{
temp=head;
while(temp!=NULL)
{
if((temp->data)< key){
newnode->prev=temp->prev; //<-- BOOM!
newnode->next=temp; //<-- BOOM!
temp->prev=newnode;
break;
}
else{
temp=temp->next;
}
}
}
}
It's not really clear what you're trying to achieve there. If this really is a find function, it should not be attempting to perform operations on nodes or copy any data.
All you really need is something like this:
struct NodeType* find_node(int key)
{
for(struct NodeType* temp = head; temp != NULL; temp = temp->next)
{
if (temp->data == key)
return temp;
}
return NULL;
}

linked list using double pointers

Using double pointers first time to create and display linked list
#include "stdio.h"
#include "stdlib.h"
struct node
{
int data;
struct node * next;
};
void Insert(struct node **, int , int );
void display(struct node *);
int main()
{
int c, data, position;
struct node* head;
do{
printf("Enter a choice :\n");
printf("1. Add an element.\n");
printf("2. Del an element.\n3.Display List.\n");
printf("4.Delete linked list.\n5.Exit.\n");
printf("Your Choice :");
scanf("%d",&c);
switch(c){
case 1 :
printf("\nEnter data and position :\n");
scanf("%d %d",&data,&position);
Insert(&head,data,position);
break;
case 2 :
break;
case 3 :
printf("Linked List : \n");
display(head);
break;
case 4 :
break;
case 5 :
exit(0);
default :
printf("Invalid Choice.\n");
break;
}
}while(1);
return 0;
}
void Insert(struct node **ptrhead, int item, int position){
struct node *p,*newnode;
//node creation.
newnode = (struct node *)malloc(sizeof(struct node));
if (!newnode)
{
printf("Memory Error.\n");
return;
}
newnode->next = NULL;
newnode->data = item;
p = *ptrhead;
// Creates initial node
if (!(p->data))
{
p = newnode;
}
// insertion at beginning
if (position==1)
{
newnode->next = p;
p = newnode;
free(newnode);
}
// insertionn at middle or end.
else
{
int i=1;
while(p->next!=NULL && i<position-1){
p=p->next;
i++;
}
newnode->next = p->next;
p->next = newnode;
}
*ptrhead = p;
};
// Display Linked list
void display(struct node *head){
if (head)
{
do{
printf("%d\n", head->data);
head = head->next;
}while(head->next);
}
};
I will add functions for deletion and other operations later. Right now , I just want to insert and display fns to work . But output comes as infinitely running loop with wrong values. I cannot figure out what's wrong in my code , please help ?
Thanks in advance.
Not sure why somebody would be writing this type of C today, looks like maybe I'm doing your homework for you... In any case, you asked to fix your code, not rewrite it, so here's the minimum set of changes.
head should be initialized to NULL.
if (!(p->data)) is not right. That if statement should just be:
// Creates initial node
if (!p)
{
*ptrhead = newnode;
return;
}
Remove free(newnode);.
The insert at middle/end code could be
int i = 1;
struct node *n = p;
while (n->next != NULL && i<position - 1){
n = n->next;
i++;
}
newnode->next = n->next;
n->next = newnode;
The final insert function:
void Insert(struct node **ptrhead, int item, int position)
{
struct node *p, *newnode;
//node creation.
newnode = (struct node *)malloc(sizeof(struct node));
if (!newnode)
{
printf("Memory Error.\n");
return;
}
newnode->next = NULL;
newnode->data = item;
p = *ptrhead;
// Creates initial node
if (!p)
{
*ptrhead = newnode;
return;
}
// insertion at beginning
if (position == 1)
{
newnode->next = p;
p = newnode;
}
// insertionn at middle or end.
else
{
int i = 1;
struct node *n = p;
while (n->next != NULL && i<position - 1){
n = n->next;
i++;
}
newnode->next = n->next;
n->next = newnode;
}
*ptrhead = p;
}
Your print function isn't quite right, just make it:
// Display Linked list
void display(struct node *head)
{
while (head)
{
printf("%d\n", head->data);
head = head->next;
}
}

Segfault while printing linked list after stack clear

To be more specific, this code is supposed to be a lesser clone of the Unix function dc. The linked list seems to be working fine. If I attempt to use c to clear the memory, add more numbers, then print again with f I get a segfault. It seems to be printing what should be the Null Node in the linked list.
Interaction:
$ ./test
1 2 3
f
3
2
1
c
4 5
f
5
4
0
Segmentation Fault
Here's the code itself:
#include <stdio.h>
#include <stdlib.h>
struct Node{
int val;
struct Node *next;
};
void cons_node(struct Node **head, int num)
{
struct Node *newNode = malloc(sizeof(struct Node));
newNode->val = num;
newNode->next = NULL;
if (*head == NULL){
*head = newNode;
}
else {
newNode->next = *head;
*head = newNode;
}
}
I'm assuming the problem lies here in the display func:
void display_list(struct Node *head)
{
struct Node *current = head;
while(current != NULL)
{
printf("%d\n", current->val);
current = current->next;}
}
void print_top(struct Node *head)
{
printf("%d\n", head->val);
}
or here in the clear func:
void clear_stack(struct Node *head)
{
struct Node *current;
while ((current = head)!= NULL) {
head = head->next;
free(current);
}
}
void vorpal_func(struct Node *head)
{
struct Node *current;
current = head;
free(current);
}
int main(){
int input;
int first = 1;
char quit = 'n';
char inputchar = ' ';
struct Node *head = NULL;
while (quit == 'n'){
if (scanf("%d", &input) == 1){
cons_node(&head, input);
first = 0;
}
else{
inputchar = getchar();
if(first == 1)
printf("List is empty\n");
else{
switch (inputchar){
case 'q':
quit = 'y';
break;
case 'E':
quit = 'y';
break;
case 'f':
display_list(head);
break;
case 'p':
print_top(head);
break;
case 'c':
clear_stack(head);
first = 1;
break;
case 't':
vorpal_func(head);
break;
}
}
}
}
return 0;
}
I've been attempting to figure out the problem for a few hours now. Any tips?
You don't clear your head after calling clear_stack, so when you add your next node, the next pointer is set to something that points into memory that has been freed. Or you could pass a pointer to head to clear_stack if you preferred.
void clear_stack(struct Node **head)
{
while (*head != NULL)
{
Node *current = *head;
*head = current->next;
free(current);
}
}
In passing, cons_node could be written like this
void cons_node(struct Node **head, int num)
{
struct Node *newNode = malloc(sizeof(struct Node));
newNode->val = num;
newNode->next = *head;
*head = newNode;
}

LinkedList functions crash in c

I implemented a linked list in c. when i test it, whenever i reach display function or insert at the end the program crashes. These are the functions:
struct Node
{
char data;
struct Node *next;
};
struct LinkedList
{
struct Node *head;
};
void insertAtBeginning(struct LinkedList *LL, char ele)
{
struct Node *new = (struct Node*)malloc(sizeof(struct Node));
new->data = ele;
new->next = NULL;
if(new->data == '\n')return;
if(LL->head==NULL)LL->head = new;
else
{
new->next=LL->head;
LL->head=new;
}
}
void insertAtTheEnd(struct LinkedList *LL, char ele)
{
struct Node *new = (struct Node*) malloc(sizeof(struct Node));
new->data = ele;
new->next = NULL;
if(LL->head==NULL){LL->head=new;return;}
struct Node *current = LL->head;
while(current->next != NULL) {current = current->next;}
current->next = new;
}
void deleteNode(struct LinkedList* LL, char ele)
{
struct Node *current = LL->head;
struct Node *temp = LL->head;
while(current->next->data!=ele && current!=NULL)current=current->next;
temp=current->next;
current->next=current->next->next;
free(temp);
}
void deleteFirstNode(struct LinkedList* LL)
{
struct Node *temp;
if(LL->head != NULL)
{
temp = LL->head;
LL->head = LL->head->next;
free(temp);
}
}
void displayLinkedList(struct LinkedList LL)
{
struct Node *current = LL.head;
printf("List: ");
while(current != NULL)
{
printf("%c",current->data);
current = current->next;
}
printf("\n");
}
This is the main:
main()
{
struct LinkedList LL;
char c = '0';
//Inserting at beginning
printf("Type a string. Press Enter to end: ");
while(c != '\n')
{
scanf("%c",&c);
insertAtBeginning(&LL, c);
}
printf("List: ");
displayLinkedList(LL);
printf("\n");
//Inserting at end
c='0';
printf("Type a string. Press Enter to end: ");
while(c != '\n')
{
scanf("%c",&c);
insertAtTheEnd(&LL, c);
}
printf("List: ");
displayLinkedList(LL);
printf("\n");
//Remove
printf("Enter a char to remove: ");
scanf("%c",&c);
deleteNode(&LL, c);
printf("\n");
printf("List: ");
displayLinkedList(LL);
printf("\n");
deleteFirstNode(&LL);
printf("List: ");
displayLinkedList(LL);
}
of course This is done after inserting the necessary libraries.
you have to set NULL to next when you create element. if you do not do it, your while loop behaviour will be buggy
void insertAtTheEnd(struct LinkedList *LL, char ele)
{
struct Node *new = (struct Node*) malloc(sizeof(struct Node));
new->next = NULL;
new->data = ele;
if(LL->head == NULL) LL->head = new;
else
{
struct Node *current = LL->head;
while(current->next != NULL) {current = current->next;}
current->next = new;
}
}
, and do same for other functions.
also you have to set NULL to your LinkedList.head. so, set NULL when you define LinkedList
struct LinkedList LL;
LL.head = NULL;
i asume the line if(current = LL->head) is wrong
bacause temp = current->next would crash if the result is NULL
otherwise the code after the if statement doesnt makes sense
There are some instances where you will try to insert at the end. When you have something of the form node_new->next->prev = node, you must check to make sure that node_new->next is not NULL, because NULL does not have any type and thus does not have a prev field.
You may also consider making all of your functions return int, so that you can know if and what goes wrong.

Resources