Segmentation fault in a simple linked list? - c

I am trying to implement a simple linked list. When I tried compiling its not showing any errors. But when while running it, its giving segmentation fault. I analysed the code but I'm not able to find any fault, might be wrong in my side, I don't know.
Please help me find the fault in the code.
Thanks in advance for all the suggestions
#include<stdio.h>
#include<stdlib.h>
struct node{
int data;
struct node* next;
};
void push(struct node** first, int data){
struct node* new_node;
new_node =(struct node*)malloc(sizeof(struct node));
/*printf("Enter the data\n");
scanf("%d",&new_node->data);*/
new_node->data = data;
new_node->next= NULL;
if(*first==NULL){
*first = new_node;
return;
}
new_node->next= *first;
*first = new_node;
}
void insert_node(struct node* prv, int data){
if(prv==NULL){
printf("previous node cannot be null\n");
return;
}
struct node* new_node;
new_node = (struct node*)malloc(sizeof(struct node));
/* printf("Enter the data\n");
scanf("%d",&new_node->data); */
new_node->data = data;
new_node->next = prv->next;
prv->next = new_node;
}
void append(struct node** first, int data){
struct node* last;
last = (struct node*)malloc(sizeof(struct node));
/* printf("Enter the data\n");
scanf("%d",&last->data); */
last->data = data;
last->next = NULL;
struct node* pre = *first;
if(*first == NULL){
*first = last;
}
while(pre->next!=0)
{pre = pre->next;}
last->next = pre->next;
pre->next = last;
}
void print(struct node* first){
if(first==NULL){
printf("There is no linked list to print\n");
}
while(first!=NULL){
printf("%d ",first->data);
first = first->next;
}
printf("\n");
}
int main()
{
struct node* first=NULL;
append(&first, 6);
push(&first, 7);
push(&first, 1);
append(&first, 4);
insert_node(first->next, 8);
printf("The Linked List is: \n");
print(first);
return 0;
}

You got your segv inside the append function:
void append(struct node** first, int data){
struct node* last;
last = (struct node*)malloc(sizeof(struct node));
last->data = data;
last->next = NULL;
struct node* pre = *first; // <-- pre = NULL
if(*first == NULL){
*first = last;
}
while(pre->next!=0)
{pre = pre->next;} //<-- referencing NULL
last->next = pre->next;
pre->next = last;
}
Solution: add a return inside the if.
if(*first == NULL){
*first = last;
return;
}

Related

What is the logical error in my attempt to implement the insertion of nodes in the linked list?

I'm unable to get an output for inserting nodes at the beginning, end, and after a given node. I'm not very sure if there is anything that I missed out in the main(). I'm unable to point out my logical error in the program
`
#include<stdio.h>
#include<stdlib.h>
struct node{
int data;
struct node *next;
};
//Inserts at the begining
void push(struct node **head, int x){
struct node *newnode = (struct node *)malloc(sizeof(struct node));
newnode->data = x;
*head = newnode;
newnode->next = (*head);
*head = newnode;
}
//Insert at the last
void append(struct node **head, int x){
struct node *temp;
struct node* newnode = (struct node*)malloc(sizeof(struct node));
newnode->data = x;
newnode->next = 0;
if(*head == 0){
*head = newnode;
}
temp = *head;
while(temp->next != 0){
temp = temp->next;
}
temp->next = newnode;
}
//inserting at a given node
void insertAfter(struct node* temp, int x){
if(temp == NULL){
printf("previous node cannot be NULL");
}
struct node* newnode = (struct node*)malloc(sizeof(struct node));
newnode->data = x;
newnode->next = temp->next;
temp->next = newnode;
}
void printList(struct node *temp){
while(temp->next != NULL){
printf("%d",temp->data);
}
temp = temp->next;
}
int main(){
struct node *head = NULL;
append(&head,6);
push(&head, 7);
push(&head, 1);
append(&head, 4);
insertAfter(head->next, 8);
printf("Created linked list is:\n");
printList(head);
return 0;
}
`
The output is 1 7 8 6 4
But I'm getting no output and no errors as well
Within the function print_list there can be an infinite loop because this statement
temp = temp->next;
is placed after the while loop
void printList(struct node *temp){
while(temp->next != NULL){
printf("%d",temp->data);
}
temp = temp->next;
}
The function can look for example the following way
void printList( const struct node *head )
{
for ( ; head != NULL; head = head->next )
printf( "%d -> ", head->data );
}
puts( "null" );
}
Pay attention to that within the function push this statement
*head = newnode;
is present twice.
Also the functions are unsafe because there is no check whether memory was allocated successfully within the functions.
For example the function append could be declared and defined the following way
//Insert at the last
int append( struct node **head, int x )
{
struct node *newnode = malloc( sizeof( *newnode ) );
int success = newnode != NULL;
if ( success )
{
newnode->data = x;
newnode->next = NULL;
while ( *head != NULL ) head = &( *head )->next;
*head = newnode;
}
return success;
}

Duplicating a linked list without using recursion

I'm trying to figure out how to duplicate a linked list, and after debugging on Vs code I'm getting a segmentation fault on cuurent->data = temp->data;
and I'm not sure why this is happening.
and this is the code:
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node* next;
};
struct node* head;
struct node* head2;
struct node* Insert(struct node* head, int x)
{
struct node* temp = (struct node*)malloc(sizeof(struct node));
temp->data = x;
temp->next = head;
return temp;
}
void Print(struct node* head)
{
struct node* tmp1 = head;
printf("List is:");
while (tmp1 != NULL) {
printf(" %d", tmp1->data);
tmp1 = tmp1->next;
}
printf("\n");
}
struct node* dupe(struct node* head, struct node* head2)
{
if (head == NULL)
return NULL;
struct node* temp = head;
struct node* prev = NULL;
struct node* cuurent = (struct node*)malloc(sizeof(struct node));
cuurent->data = temp->data;
if (head2 == NULL) {
cuurent->next = head2;
head2 = cuurent;
}
while (temp != NULL) {
temp = temp->next;
cuurent = (struct node*)malloc(sizeof(struct node));
cuurent->data = temp->data;
cuurent->next = prev;
prev = cuurent;
}
return head2;
}
int main(void)
{
head = NULL;
head2 = NULL;
head = Insert(head, 4);
head = Insert(head, 2);
head = Insert(head, 3);
head = Insert(head, 5);
head2 = dupe(head, head2);
Print(head);
Print(head2);
}
As pointed out in the comments,
while (temp != NULL) {
temp = temp->next;
changes the value of temp immediately after guarding against a null pointer value.
This eventually means
cuurent->data = temp->data;
will cause Undefined Behaviour by dereferencing temp when it is the null pointer value.
You can apply the exact same looping principles shown in Print to copy the list. The only difference being you must save a pointer to the first node.
The same principle can be used again when it comes time to free the memory.
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
struct node *insert(struct node *next, int x)
{
struct node *n = malloc(sizeof *n);
n->data = x;
n->next = next;
return n;
}
void print_list(struct node *head)
{
printf("List is: ");
while (head) {
printf("%d ", head->data);
head = head->next;
}
printf("\n");
}
void free_list(struct node *head)
{
struct node *t;
while (head) {
t = head->next;
free(head);
head = t;
}
}
struct node *copy_list(struct node *head)
{
struct node *root = NULL;
for (struct node *current; head; head = head->next) {
struct node *new = insert(NULL, head->data);
if (!root)
root = new;
else
current->next = new;
current = new;
}
return root;
}
int main(void)
{
struct node *head = NULL;
head = insert(head, 4);
head = insert(head, 2);
head = insert(head, 3);
head = insert(head, 5);
struct node *head2 = copy_list(head);
print_list(head);
print_list(head2);
free_list(head);
free_list(head2);
}
Output:
List is: 5 3 2 4
List is: 5 3 2 4

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.

Expected expression before 'Node'

I've been messing aroung with the linked list implementation in C and got stuck at this problem: why is it giving me expected expression before 'Node' in the following lines?:
Node *newNode1= malloc(sizeOf(Node));
Node *newNode2= malloc(sizeOf(Node));
Node *newNode3= malloc(sizeOf(Node));
Node *newNode4= malloc(sizeOf(Node));
I've never seen such problems in C before. What went wrong ?
Code:
#include <stdio.h>
#include <stdlib.h>
typedef struct Node_{
int data;
struct Node_ *next;
}Node;
void insertNodeBegin(Node **head, Node *newNode){
if((*head)==NULL){
(*head)->next = NULL;
*head = newNode;
}
else{
newNode->next = (*head)->next;
(*head)->next = newNode;
}
}
void printList(Node *head){
Node *current = head;
while(current != NULL){
printf("%d ", current->data);
current = current->next;
}
}
int main()
{
Node *head = NULL;
Node *newNode1= malloc(sizeOf(Node));
newNode1->data = 12;
Node *newNode2 = malloc(sizeOf(Node));
newNode2->data = 16;
Node *newNode3 = malloc(sizeOf(Node));
newNode3->data = 55;
Node *newNode4 = malloc(sizeOf(Node));
newNode4->data = 8;
insertNodeBegin(&head, newNode1);
insertNodeBegin(&head, newNode2);
insertNodeBegin(&head, newNode3);
insertNodeBegin(&head, newNode4);
printList(head);
return 0;
}
sizeOf(Node) should be sizeof(Node), note the small o. After all this is C, not Java. :)
In short reorder if commands inside insertNodeBegin()
if(*head == NULL){
*head = newNode;
(*head)->next = NULL;
}
Because in first execution of program head points to NULL and for it we haven't any allocated memory. As head in first execution not points to a Node location using head -> next not valid and cause segmentation fault in run time.
In node creation with malloc() we must check is memory allocation successful or not. for that i use createNode() function.
We check if memory allocation for Node is OK then add that Node to list. And finally Use void as main(void) argument.
After these change your code becomes
Code
#include <stdio.h>
#include <stdlib.h>
typedef struct Node_{
int data;
struct Node_ *next;
}Node;
void insertNodeBegin(Node **head, Node *newNode){
if(*head == NULL){
*head = newNode;
(*head)->next = NULL;
}
else{
newNode->next = (*head)->next;
(*head)->next = newNode;
}
}
void printList(Node *head){
Node *current = head;
while(current != NULL){
printf("%d ", current->data);
current = current->next;
}
}
int createNode(Node **node, int value){
*node = malloc(sizeof(Node));
if(*node){
(*node)->data = value;
return 1;
}else{
fprintf(stdout, "%s", "can't allocate ...\n");
return 0;
}
}
int main(void)
{
Node *head = NULL;
Node *newNode1;
Node *newNode2;
Node *newNode3;
Node *newNode4;
if(createNode(&newNode1, 12)) {
insertNodeBegin(&head, newNode1);
}
if(createNode(&newNode2, 16)) {
insertNodeBegin(&head, newNode2);
}
if(createNode(&newNode3, 55)) {
insertNodeBegin(&head, newNode3);
}
if(createNode(&newNode4, 8)) {
insertNodeBegin(&head, newNode4);
}
printList(head);
return 0;
}

Linked list implementation in c without using double-pointer

I have implemented a simple linked list in C language, but can it be implemented without using double-pointer(**).I want to implement same program by using only single pointers.
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *next;
};
void push(struct node** head_ref, int new_data)
{
struct node* new_node = (struct node*) malloc(sizeof(struct node));
new_node->data = new_data;
new_node->next = (*head_ref);
(*head_ref) = new_node;
}
void append(struct node** head_ref, int new_data)
{
struct node* new_node = (struct node*) malloc(sizeof(struct node));
struct node *last = *head_ref; /* used in step 5*/
new_node->data = new_data;
new_node->next = NULL;
if (*head_ref == NULL)
{
*head_ref = new_node;
return;
}
while (last->next != NULL)
last = last->next;
last->next = new_node;
return;
}
void printList(struct node *node)
{
while (node != NULL)
{
printf(" %d ", node->data);
node = node->next;
}
}
int main()
{
struct node* head = NULL;
append(&head, 6);
push(&head, 7);
push(&head, 1);
append(&head, 4);
printf("\n Created Linked list is: ");
printList(head);
getchar();
return 0;
}
Is it possible to replace "struct node** head_ref" with "struct node* head_ref"?
Changed code after suggestions(still not getting output)
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *next;
};
struct node* push(struct node* head, int new_data)
{
struct node* new_node = (struct node*) malloc(sizeof(struct node));
new_node->data = new_data;
new_node->next = head;
head = new_node;
return head;
}
struct node* append(struct node* head, int new_data)
{
struct node* new_node = (struct node*) malloc(sizeof(struct node));
struct node *last = head; /* used in step 5*/
new_node->data = new_data;
new_node->next = NULL;
if (head == NULL)
{
head = new_node;
return head;
}
while (last->next != NULL)
last = last->next;
last->next = new_node;
return head;
}
void printList(struct node *node)
{
while (node != NULL)
{
printf(" %d ", node->data);
node = node->next;
}
}
int main()
{
struct node* head = NULL;
head= append(&head, 6);
head=push(&head, 7);
head=push(&head, 1);
head=append(&head, 4);
printf("\n Created Linked list is: ");
printList(head);
getchar();
return 0;
}
Yes, you can rewrite this code using only single pointers, but you would have to change the semantic of your API and the pattern in which it is used.
Essentially, you replace the second level of indirection in
void push(struct node** head_ref, int new_data)
with a client-side assignment, i.e.
struct node* push(struct node* head, int new_data)
This means that instead of
push(&head, num);
the caller will have to write
head = push(head, num);
Same goes for the implementation of append.
Replace (&head,6) with (head,6).As you are not passing the address of the head, on receiving end you have push(struct node* head, int new_data).Rest all have been clarified by above given answer
Another solution is to create an empty node called head, and then create a pointer to that node called list. You can then pass list to all of the functions, like this
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *next;
};
void push(struct node *list, int new_data)
{
struct node* new_node = malloc(sizeof(struct node));
new_node->data = new_data;
new_node->next = list->next;
list->next = new_node;
}
void append(struct node *list, int new_data)
{
while ( list->next != NULL )
list = list->next;
push( list, new_data );
}
void printList(struct node *node)
{
for ( node=node->next; node != NULL; node=node->next )
printf(" %d ", node->data);
printf( "\n" );
}
int main( void )
{
struct node head = { 0, NULL };
struct node *list = &head;
append(list, 6);
push(list, 7);
push(list, 1);
append(list, 4);
printf("\n Created Linked list is: ");
printList(list);
getchar();
return 0;
}

Resources