Seg fault linked list recursion in C - c

I can't figure out why I'm seg faulting. The basic idea is to insert integers in order recursively using a linked list.
node* insert(node** head, int integer)
{
node* temp = malloc(sizeof(node));
node* temp1;
node* newNode;
if(*head == NULL)
{
temp->num = integer;
temp->next = *head;
*head = temp;
}
else if((*head)->num > integer)
{
temp = *head;
temp1 = temp->next; //breaks the link
temp->next = newNode; //creates a new node
newNode->num = integer; //adds int
newNode->next = temp1; //links new node to previously broken node
temp1->next = *head; //next node is NULL
*head = temp1; //Makes next node head again
}
else
insert(&((*head)->next), integer);
return(temp);
}
I ran this code in GDB and it seg faults at temp1->next = *head but I don't understand why. I even put notes to help myself but I guess it isn't working. Can someone please tell me why I'm seg faulting? Thanks.

temp1 = temp->next;
should be before
temp = *head;
In case that the (*head)->num > integer and If you want to insert the integer in the header than your code is complicated and wrong. you can do it in this way:
else if((*head)->num > integer)
{
temp->next = *head;
temp->num = integer;
*head = temp;
}
and the
temp = malloc(sizeof(node));
should be called only into the
if(*head == NULL)
and into
else if((*head)->num > integer)
So your final function could be like this
node* insert(node** head, int integer)
{
node* temp;
if(*head == NULL)
{
temp = malloc(sizeof(node));
temp->num = integer;
temp->next = *head;
*head = temp;
}
else if((*head)->num > integer)
{
temp = malloc(sizeof(node));
temp->next = *head;
temp->num = integer;
*head = temp;
}
else
temp = insert(&((*head)->next), integer);
return(temp);
}
I test the insert function with:
int main (void) {
node *tmp, *head = NULL;
insert(&head, 5);
insert(&head, 7);
insert(&head, 3);
insert(&head, 6);
insert(&head, 4);
insert(&head, 2);
for (tmp = head; tmp!=NULL; tmp = tmp->next) {
printf("tmp->num %d\n",tmp->num);
}
}
and it works succefully!
$ ./test
tmp->num 2
tmp->num 3
tmp->num 4
tmp->num 5
tmp->num 6
tmp->num 7

So the first time you go through this, head is null and you've got a case for that.
The next time through, head has a pointer, and there is no next node. The head->next is NULL.
So when you get to:
temp1 = temp->next;
That's setting it equal to NULL. And when you get to
temp1->next = *head; //next node is NULL
Whoa there, temp1 is null. There is no such thing as temp1->next, that's looking for a structure where there is none.
Edit:
And you're throwing away the memory you just allocated when you set temp = *head. You probably shouldn't be allocating memory until you're sure you need it. I mean, you call a new instance of insert() every time the number is less than the target. Each pass you allocate some memory that you don't actually use. And you probably wanted to allocate memory for newnode, not temp.
And you should probably use a better naming scheme. I mean, the second time you call insert, it's no longer the head. integer could be something more like intToInsert or newValue. temp1 is more like savedTail. Minor issue, but it helps keep things straight, and it's a good habit to get into.
Finally, think about what happens when you've gone through the list, found where the new item belongs, made a new node, set it's ->next field to the rest of the tail, and returned. ... now what? the previous node has a next value that's still pointing to what it was before. You need to update that link as well.

Lets assume that the linked list currently has only one node.
So *head = some node.
*head->next = NULL.
Now lets look into the code:
node* insert(node** head, int integer)
{
node* temp = malloc(sizeof(node));
node* temp1;
node* newNode;
if(*head == NULL) // condition = false
{
temp->num = integer;
temp->next = *head;
*head = temp;
}
else if((*head)->num > integer) // let's assume condition = true
{
temp = *head;
temp1 = temp->next; //breaks the link // temp1 = NULL
temp->next = newNode; //creates a new node // temp1 is not changed
newNode->num = integer; //adds int
newNode->next = temp1; //links new node to previously broken node
temp1->next = *head; //next node is NULL // NULL->next !!!
*head = temp1; //Makes next node head again
}
else
insert(&((*head)->next), integer);
return(temp);
}

*head = temp1;
should be before
temp1->next = *head;

Related

What is causing segmentation fault in append Node function in doubly linked list?

My doubly linked list implementation is as follows that each node holds an array of four values
#define EMPTYNODE 0
struct node {
short data[4]; // pay attention
struct node* next;
struct node* prev;
};
typedef struct node nodeQ_t;
typedef enum{
LIST_FALSE = 0,
LIST_TRUE = 1,
} status_t;
nodeQ_t* createNode(short values[4]){
nodeQ_t* node = (nodeQ_t*)malloc(sizeof(node));
for(int i=0; i < 4; i++){
node->data[i] = values[i];
}
node->next = EMPTYNODE;
node->prev = EMPTYNODE;
return node;
}
now I am trying to write append function in a way that I supply it head and a node created in createNode function so that it would append it to the list.... but it creates a segmentation fault...
status_t appendNode(nodeQ_t* head, nodeQ_t* newNode){
if(head == EMPTYNODE || newNode == EMPTYNODE){
return LIST_FALSE;
};
nodeQ_t* currentNode = head;
while(currentNode != EMPTYNODE){
if(currentNode->next == EMPTYNODE){ //it means that current node is tail
currentNode->next = newNode; //segmenttion fault arises at exactly this line
newNode->prev = currentNode;
}
currentNode = currentNode->next;
}
return LIST_TRUE;
}
please let me know what is the reason for that...
for your reference my main function is
int main(){
short array[4] = {1,2,3,4};
nodeQ_t* head = createNode(array);
printList(head);
short array2[4] = {5,6,7,8};
nodeQ_t* newNode = createNode(array2);
appendNode(head, newNode);
printList(head);
return 0;
}
if you need any further information or explanation for anything please do let me know
As mentioned in the comments, you need to break out of the loop once you've reached the end:
while(currentNode != EMPTYNODE) {
if (currentNode->next == EMPTYNODE) {
currentNode->next = newNode;
newNode->prev = currentNode;
// need a break here
}
currentNode = currentNode->next;
// When at the end of the list the 1st time through,
// currentNode is the newly created node because you have
// currentNode->next = newNode
// then
// currentNode = currentNode->next
// On the next iteration, the new node next ends up getting pointed to itself
// since on that iteration newNode and currentNode are the same.
// and you end up with an infinite loop.
}
Another option is to loop on currentNode->next:
while (currentNode->next) {
currentNode = currentNode->next;
}
currentNode->next = newNode;
newNode->prev = currentNode;
I should note that this works because you previously ensured that currentNode is not NULL.
Also, your allocation here is wrong:
nodeQ_t* node = (nodeQ_t*)malloc(sizeof(node));
Because node is a pointer and sizeof(node) is the size of a pointer, not the size of struct node. Should be
nodeQ_t* node = (nodeQ_t*)malloc(sizeof(*node));
You end up in endless loop:
while(currentNode != EMPTYNODE){
if(currentNode->next == EMPTYNODE){ //it means that current node is tail
currentNode->next = newNode; //segmenttion fault arises at exactly this line
newNode->prev = currentNode;
}
currentNode will always be different than EMPTYNODE.
Add break or return after adding new element:
while(currentNode != EMPTYNODE){
if(currentNode->next == EMPTYNODE){ //it means that current node is tail
currentNode->next = newNode; //segmenttion fault arises at exactly this line
newNode->prev = currentNode;
return LIST_TRUE;
}

Linked list troubles list not linking to head pointer

I have been having trouble with this linked list specifically it seems like my head pointer is not linking to the rest of my list and I am confused as to why it is not. Where I insert my head pointer by pointer by reference it is not connected to the linked list referenced in main. unless the list is not linked together in the main function and I am missing something.
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int number;
struct node * next;
} Node;
typedef Node * Nodeptr;
void printlist (Node * head){
Node * n = head;
while(n != NULL){
printf("%d\n",n ->number);
n = n ->next;
}
}
void sumlist (Node * head){
Node * n = head;
int sum;
while(n != NULL){
sum = n ->number +sum;
n = n ->next;
}
printf("the total of all numbers in this list is %d",sum);
}
search(head){
}
int main(){
int i =0;
Nodeptr head=NULL;
if((head = malloc(sizeof(Node))) == NULL)
return 0;
head->number =rand()%50+50;
head ->next = malloc(sizeof(Node));
int n;
Nodeptr newnode = NULL;
for(n=0;n<99;n++)
{
newnode = malloc(sizeof(Nodeptr));
newnode->number = rand()%50+50;
newnode->next =NULL;
head -> next = newnode;
}
printlist(head);
sumlist(head);
return 0;
}
The error is that you are linking everything as next of head
head -> next = newnode;
You need to use a pointer that gets updated:
Nodeptr newnode = NULL;
Nodeptr last = head;
for(n=0;n<99;n++)
{
newnode = malloc(sizeof(Nodeptr));
newnode->number = rand()%50+50;
newnode->next =NULL;
last -> next = newnode;
last = last->next;
}
You should also change this:
head ->next = malloc(sizeof(Node)); // otherwise you will lose this element.
into
head ->next = NULL;
You execute these steps in a loop:
newnode = malloc(sizeof(Nodeptr));
newnode->number = rand()%50+50;
newnode->next =NULL;
head -> next = newnode;
You are setting the newnode->next to point to null, and head->next to point to newnode.
This means, each time through the loop your head gets a new next, and that's it.
Effectively, each time you pass through the loop you drop the previous newnode on the floor, and link to a new one. At the end, you'll have head pointing to 1 node, and you'll have 98 nodes dropped on the floor that you can't reach.
You need to either maintain a "tail" pointer, or a copy of "head", and set head or tail or something to the most recent value of newnode. Then, you can set tail->next = newnode; tail = newnode; which will continually extend your list, rather than overwriting the same head->next each time.

why am I getting out of bounds error in this linked list? C

So am making a linked list. printing it out. and reversing it. and then printing it out. first time I make it and print it out. everything works fine. but when I reverse it. it reverses successfully. but when I print it. I go out of bounds even though I use the same code I did first.
Here is the reverse function
void reverse_list(Node_ptr* head){
Node_ptr temp2;
Node_ptr temp3 = NULL;
temp2 = (Node_ptr)malloc(sizeof(Node));
temp3 = (Node_ptr)malloc(sizeof(Node));
if (temp2==NULL || temp3==NULL)
{
printf("Failed to allocate node\n");
exit(1);
}
while (*head!=NULL) {
temp2 = (*head)->next;
(*head)->next = temp3;
temp3 = (*head);
(*head) = temp2;
}
*head = temp3;
}
here is the print function
temp = head;
while (temp != NULL)
{
printf("%d\n", temp->data);
temp = temp->next;
}
reverse_list(&head);
temp = head;
while (temp != NULL)
{
printf("%d\n", temp->data);
temp = temp->next;
}
for some reason it tries to print garbage after the last element
Do this:
/* Function to reverse the linked list */
void reverse(struct node** head_ref)
{
struct node* prev = NULL;
struct node* current = *head_ref;
struct node* next;
while (current != NULL)
{
next = current->next;
current->next = prev;
prev = current;
current = next;
}
*head_ref = prev;
}
It's actually your code with a couple of fixtures, i.e.:
1) You don't need to allocate space, just swap pointers.
2) Use meaningful names for your temporary containers.
The first time you go through the loop
while (*head!=NULL) {
temp2 = (*head)->next;
(*head)->next = temp3;
temp3 = (*head);
(*head) = temp2;
}
(*head)->next is assigned a newly allocated node. Who knows what this node contains? It is probably not zeroed out, and will point to a random point in memory.
You should initialize temp3 to NULL to fix this problem.

Inserting a node at the end of a linked list

#include <stdio.h>
#include <conio.h>
struct node
{
int data;
struct node* next;
};
int main()
{
struct node* head = NULL;
struct node* second = NULL;
struct node* third = NULL;
head = (struct node*)malloc(sizeof(struct node));
second = (struct node*)malloc(sizeof(struct node));
third = (struct node*)malloc(sizeof(struct node));
head->data = 1;
head->next = second;
second->data = 2;
second->next = third;
third->data = 3;
third->next = NULL;
struct node* new1;
struct node* temp1;
temp1 = head;
while(temp1->next != NULL)
{
temp1 = temp1->next;
}
new1 = (struct node*)malloc(sizeof(struct node));
temp1->next = new1;
new1->data = 5;
new1->next = NULL;
while(temp1 != NULL)
{
printf("%d ",temp1->data);
temp1 = temp1->next;
}
return 0;
}
This is the program for inserting a node at the end of linked list. The expected output is = 1 2 3 5, 5 is the new node's value here. But the current output is = 3 5. I don't know where am I wrong. Any answer will be appreciated.
while(temp1->next != NULL)
{
temp1 = temp1->next;
}
After this loop your temp1 is at the end of the list and you are adding a node at the end of the list.
Now you are trying to print from temp1 obviously you will get only 2 nodes new one and the one before it.
If you want the whole list print from head.
Just before printing after adding your new node. Point temp1 to head.
temp1 = head;
while(temp1 != NULL)
{
printf("%d ",temp1->data);
temp1 = temp1->next;
}
One thing to remember when using something like you did to get to the end of the list: If you just say third->next = first, then it will go on forever. This is something to watch out for, and also something you may want to play with. Maybe consider adding a list_size integer somewhere so that infinite looping does not happen.

Doubly Linked List Pointer Confusion

Below is the code for inserting a node in a doubly linked list.
struct dllist
{
int data;
struct dllist *prev, *next;
};
void DLLInsert(struct dllist **head, int position, int data)
{
int k = 1;
struct dllist *temp, *newNode;
newNode = (struct dllist *)malloc(sizeof(struct dllist));
if (!newNode)
{
printf("Memory Error\n");
}
newNode->data = data;
if (position == 1)
{
newNode->next = *head;
newNode->prev = NULL;
*head = newNode;
return;
}
else
{
temp = *head;
while (temp->next != NULL && k < position - 1)
{
k++;
temp = temp->next;
}
if (temp->next == NULL)
{
temp->next = newNode;
newNode->prev = temp;
newNode->next = NULL;
}
else
{
newNode->prev = temp;
newNode->next = temp->next;
temp->next = newNode;
temp->next->prev = newNode;
}
}
}
I am getting somewhat confused in the underlying pointer operations being a newbie. A **head is passed onto the function to modify it. But in case when the position>1, a copy of *head(temp) is used to modify the list compared to the case when position==1. Can anybody explain me why is it so?
Thanks
When position > 1, temp is set to *head, and the code iterates temp through the linked list to the node at index position. Effectively, you are modifying the node at index position.
When position = 1, you are modifying the head node, so you don't need to iterate.
In the case of position==1, your new element will become the new head. You already know exactly where it is. Otherwise, you need to find the position.
temp = *head;
while (temp->next != NULL && k < position - 1)
This is used to iterate through the list until you find the element in the position you are going to insert at.
temp = temp->next;
The first element you assign to temp is head, but it is replaced with the next element in each iteration.

Resources