Seg Fault: Linked List Node Insertion Function [C++] - c++

I have created a function called 'Insert' for inserting a new node in a Linked List. It takes the value and the head node for insertion.
When I manually add the nodes myself, the program runs as expected however
I get a segmentation fault when I use the function for adding a node.
I am able to make the function work with a couple of little tweaks but there's another catch, I lose the head node's property of just being a pointer, it now contains some garbage data in it which gets printed when I print the LinkedList.
The tweak I perform is:
Change Line 26 to: A->next = NULL;
Change Line 17 to: while(temp->next != NULL)
The 'segmentation fault' occurs at Line 20 (when the tweak is not done):
Line 20 -----> temp->next = addTo;
I've already tried passing the arguments by reference, using global variables for the head node and checking the logic of the function.
The logic works for manually adding a node.
I have attached the complete code below:
#include <bits/stdc++.h>
using namespace std;
struct ListNode {
int data;
ListNode *next;
};
void Insert(int x , ListNode* head)
{
ListNode* addTo = new ListNode();
addTo->data = x;
addTo->next = NULL;
ListNode* temp;
temp = head;
while(temp != NULL)
temp = temp->next;
temp->next = addTo;
}
int main()
{
ListNode* A;
A = NULL;
//Inserting A Node Manually
// ListNode* first = new ListNode();
// first->data = 9;
// first->next = NULL;
// while(A != NULL)
// A = A->next;
// A = first;
//Inserting using Insert function.
Insert(2,A);Insert(3,A);Insert(6,A);Insert(7,A);
//Printing
ListNode* temp = A;
while(temp != NULL)
{
cout << temp->data << " ";
temp = temp->next;
}
return 0;
}
I expected the node to be added to the list as the logic seems to be correct, however I am getting a segmentation fault.
Any help/insight into this would help a lot.
Thank You.

Problem 1:
while(temp != NULL)
temp = temp->next;
temp->next = addTo;
Guarantees that temp will be NULL when while(temp != NULL) exits. that means there is no temp to get the next from.
Rather than solve this here, I'm going to move on to problem 2 and kill two birds with one stone.
Problem 2:
void Insert(int x , ListNode* head)
leaves you with no way to update the caller if head is changed in the Insert function. You can change the object pointed at by head, but head itself is just a copy of an address. If you change this copy to point at another address, the caller does not know.
This means every time you call Insert(<number>, A);, A will always be NULL.
Solution:
Pass head into Insert by reference so that it can be updated.
void Insert(int x , ListNode*& head)
^ reference to pointer
head's job is to point at the first item in the list. This makes means it does the same thing as any next pointer: It points at the next item. The only difference is the name. We can get rid of this difference by adding an extra indirection, a pointer to head.
ListNode ** temp = &head;
Note that we cannot use a reference (ListNode *& temp) here because once you initialize a reference to refer to an object, it cannot be changed to refer to a different object. A pointer you can change, allowing us to iterate through the list and always point temp at the next next.
Now head or any next is simply temp. This makes head exactly the same as every other next variable and no special cases are required.
void Insert(int x , ListNode*& head)
{
ListNode* addTo = new ListNode();
addTo->data = x;
addTo->next = NULL; // consider making a smarter ListNode constructor that makes
// it impossible to forget to set next.
ListNode ** temp = &head; // we can now manipulate the address in head through temp
while(*temp != NULL) // note the dereference to get the pointed at pointer
// temp won't be null, but it could be pointing at a pointer
// that is null, and that is the end of the list
{ // I always use the optional braces. They prevent confusion.
temp = &(*temp)->next; //get pointer to the next next pointer
// we can now manipulate it exactly the same as head.
}
// we exit the loop with a pointer to the next pointer that we wish to point at
// the new list item regardless of whether it's head or the next of some later
// link in the list
*temp = addTo; // update the pointed at pointer with the new Node.
}
The Community Addition the first answer of How do I properly delete nodes of linked list in C++ demonstrates how to use the same pointer-to-pointer trick to make removing nodes easy.

Related

Why my head pointer is changing in linked list,even not passing it by reference?

I created a linked list, and made a function reverseList which takes a pointer to head and return pointer to last node.
Node* reverseList(Node *head)
{
Node* curr=head;
Node* prev=NULL;
Node* ahead;
while(curr!=NULL)
{
ahead=curr->next;
curr->next=prev;
prev=curr;
curr=ahead;
}
return prev;
}
But in main when I am doing this
int main()
{
int n;///no of elements in list
cin>>n;
Node* head=NULL;
head=createList(head,n);///creating list(it is working properly)
printList(head);
cout<<endl;
Node* temp=reverseList(head);///reversing list and storing address of list in
//new node
printList(temp);///printing reversed list properly
cout<<endl;
printList(head);///while printing this it is printing only one elements,
//which implies head pointer changes but I don't know
///how
}
My head pointer changes, and it is printing only one value. I had pass my head pointer in reverseList by value. I am providing image of output.
Comments explain fine already, trying to illustrate to make it a little clearer:
1 > 2 > 3 > 4 > NULL
^
head
Now you reverse the list, resulting in:
4 > 3 > 2 > 1 > NULL
^ ^
temp head
As you never changed head, it still points to the same node as it pointed to before the list reversal, but after reversing the list, this node is now the last one.
Side note: Forgetting to re-assign is quite a common error, so it is a good idea to encapsulate the linked list in a separate class:
class LinkedList
{
Node* _head;
public:
class Node; // just as you have already
void reverse() // now a member function
{
//reverse as you did before
// encapsulating the assignment: (!)
_head = newHead;
}
Node* head() { return _head; }
};
LinkedList l;
// ...
Node* tmp = l.head();
l.reverse();
// tmp variable points to tail...
// expecting tmp pointing to head is still an error,
// and there is no way to prevent it
// BUT the correct head can always be re-acquired:
head = l.head();
Edit in response to comment:
If you want to create a new list, you will have to copy the nodes:
Node* createReversedList(Node* head)
{
Node* cur = NULL;
while(head)
{
Node* tmp = new Node(*head);
// (provided you have an appropriate copy constructor)
tmp->next = cur;
cur = tmp;
head = head->next;
}
return cur;
}
Note the new name, reverse rather implies modifying the original list as you did.
To create a new Linked List, you need to create a new variable of Node, and perform operations on that variable.
So, the code would be something like:
Node* reverseList(Node *head)
{
Node* newRootPtr = new Node(); //Pointer to the new root. This will be returned to the calling function.
newRootPtr->next = NULL; //In the reversed list, the original head will be the last node.
Node* curr=head; //For iterations
while(curr->next!=NULL) //For every node, until the last node. Note that here, we need to stop at the last node, which will become the first node of the new List.
{
Node ahead=*(curr->next); //Create a new Node equal to the next node of the original list.
Node* aheadPtr = &ahead; //Pointer to the new node
aheadPtr->next = newRootPtr; //Point the new node to the previous node of the new list
newRootPtr = aheadPtr; //update root node
curr=curr->next;
}
return newRootPtr;
}

segmentation fault while subtracting 2 consecutive nodes of a linked list

my aim is to create a function to subtract 2 consecutive numbers and then add that result to the front of those numbers e.g.: input: 2->4->1->6->9->8->7 output: -2->2->4->-5->1->6->1->9->8->7 So this is my logic so far:
struct node
{
int data;
node *next;
};
void SubtractConsecutiveNodes()
{
if(head==NULL || head->next==NULL)
{
return;
}
node *first =head,*prev;
node *newNode;
while(first!=NULL&&first->next!=NULL)
{
newNode->data=first->data-first->next->data;
newNode->next = first;
if(head== first)
head = newNode;
else
prev->next=newNode;
prev = first->next;
first=first->next->next;
}
}
but the problem is after doing first Iteration loop seems to go into a segmentation fault and then crash.
Link to my whole code: Assignment-3
In
void SubtractConsecutiveNodes()
{
if(head==NULL || head->next==NULL)
{
return;
}
node *first =head,*prev;
node *newNode;
while(first!=NULL&&first->next!=NULL)
{
newNode->data=first->data-first->next->data;
newNode->next = first;
if(head== first)
head = newNode;
else
prev->next=newNode;
prev = first->next;
first=first->next->next;
}
}
newnode is not pointed at anything before it is dereferenced during
newNode->data=first->data-first->next->data;
A crash is one of the more polite things that can result from using an uninitialzed pointer, so a
node *newNode = new node;
is in order.
Addendum
I hate prev variables. I'm not sure why. Maybe I was murdered in a previous life or something. Anyway, There's neat trick with a pointer to a pointer you can use to get rid of prevs and, at the same time, a lot of head-specific logic.
A lot of the time multiple indirection (pointers to pointers) is frowned on, but pointers are like fire: A powerful servant, but a terrible master. Master the pointer and by Crom, you can write some cool software!
void SubtractConsecutiveNodes()
{
// if first is a pointer to a pointer to a node, we can point it at a `next`
// and eliminate the need for prev. This has the added bonus of turning head
// into just another next pointer, eliminating all of the head-specific logic.
// if(head==NULL || head->next==NULL) is identical to the while exit condition
// once head is hidden behind first. Chuck it. You don't need it.
node **first = &head;
while ((*first) != NULL && (*first)->next != NULL)
// extra level of indirection, so extra dereferencing required.
{
node *newNode = new node;
newNode->data = (*first)->data - (*first)->next->data;
newNode->next = *first;
(*first) = newNode; // places newnode directly into prev->next or head,
// whichever happens to be there.
first = &(*first)->next->next->next;
//since we added another node in we need an extra ->next
}
}

Is it necessary to use 'new' to allocate a new pointer to a struct identical to a previously existing pointer to the same struct? If so, why?

I am writing a function that inserts a new element in a singly linked linked list.
The function accepts the *head to the list, the data to be put in the new element and the position in the l-list should be inserted at.
This is the link to the programming exercise in case I've not been clear enough.
The following code works perfectly -
/*
Insert Node at a given position in a linked list
head can be NULL
First element in the linked list is at position 0
Node is defined as
struct Node
{
int data;
struct Node *next;
}
*/
Node* InsertNth(Node *head, int data, int position)
{
//Takes head of list as input and returns it after inserting a new element
//with `data` at `position` in the l-list
Node *temp = new Node;
temp = head;
Node *newn = new Node;
newn->data = data;
if(position == 0){
newn->next = head;
return newn;
}
while(--position){
temp = temp->next;
}
newn->next = temp->next;
temp->next = newn;
return head;
}
However, I don't understand why I had to use Node *temp = new Node; temp = head;.
Why doesn't simply using Node *temp = head; work?
I'm only using the temp pointer to traverse the l-list so that I can preserve the location of the head when I return the final list.
Edit - I understand that Node *temp = head; is the way to go. This was how I originally programmed it too, but I forgot to mention that this is what's giving me a segfault. When I change it to Node *temp = new Node; temp = head; it works for all the testcases(including the ones where head is NULL).
Why must this seemingly absurd mem allocation seem to make it work is what I want to know.
The code you post above leaks.
Node *temp = new Node; temp = head;
This is no good.
Node *temp = head;
This is better.
There are other problems in your code; but your analysis that it was silly to new then immediately reassign the pointer is correct. Well spotted.
The answers that were posted before mine are both wrong, sure they Point out that your code leaks, but they didn´t check the rest of the code to see if it actually does what it is supposed to do. Your code is prone to Errors, because you don´t account for the head being NULL, which is clearly stated.
// Returns the new node inserted at the given Position inside the l-list
Node* InsertNth(Node *head, int data, int position)
{
Node *newn = new Node;
newn->data = data;
newn->next = 0;
// No head, return node right away
if(!head)
{
return newn;
}
// Exception - only case where head is not returned
else if(!position)
{
newn->next = head;
return newn;
}
// Create ´temp´ which is a pointer to the next node in the list
Node *temp = head;
// The function allows passing of a signed int, make sure we stay above 0
// as the previously while(--position) would go into an endless loop
// if a signed integer were passed on to the function
while(--position > 0)
{
// Just incase the input is bad, and position exceeds the size of the list
if(!temp->next)
{
break;
}
temp = temp->next;
}
// Now that we found the place in line, insert it between the temp and the next item
// in the list. Which may also be NULL
newn->next = temp->next;
temp->next = newn;
return head;
}
Now as you can see a few changes were made, the code earlier on didn´t account for head being NULL, and it didn´t properly set the member ´next´ to 0, which would lead to a Crash eventually if someone iterated over the supposedly null-terminated single-linked list.
Use of
Node *temp = new Node;
temp = head;
causes a memory leak. Memory allocated in the first line is lost. You need to use:
Node *temp = head;

Why isn't my remove node function working?

I've checked the boards and could not find any help with this. I find it easy to implement recursive functions given base and general cases, but this doesn't work the way I do it. I'm supposed to iterate down a list until I reach the tail of a linked list. If the next node is NULL, then I have to store the value at the last node, remove that node, and return the value. So it's similar to a dequeue method, except it's performed recursively. What am I doing wrong?
int LinkedList::removeTailRec(Node *n)
{
// check for the base case(s)
if(n->next == NULL)
{
Node *tmp = new Node();
tmp = n;
int val = n->value;
tmp = NULL;
return val;
}
else
return removeTailRec(n->next);
// else call the recursive method
}
First, I recommend you use nullptr instead of NULL.
Then, onto your code. You're actually not removing anything from your list.
if(n->next == NULL)
{
Node *tmp = new Node();
^^^^^^^^^^
//Useless, and dangerous. This memory is never free'd
tmp = n;
int val = n->value;
tmp = NULL;
^^^^^^^^^^
//You just set a local variable to NULL, you're not deleting anything
return val;
}
If you want to remove the node, you'll have to keep a reference to the previous node (e.g. having a doubly linked list, that is, having a pointer to the next element and a pointer to the previous element in each node, or working on the previous node directly).
Set this previous node's next to nullptr, store the node's value and then delete the Node pointer.
One way to do this is to work with the pointer to the next node :
int LinkedList::removeTailRec(Node *n)
{
//EDIT: Adding a check for n validity
if(!n){
//Here, you should have a way of detecting
//a call to your method with a null pointer
return 0;
}
Node* nextNode = n->next;
// check for the base case(s)
if(nextNode->next == nullptr)
{
//Get the next node value
int val = nextNode->value;
//Set the current node next member to nullptr
n->next = nullptr;
//Free the last node
delete nextNode;
return val;
}
else{
return removeTailRec(n->next);
}
// else call the recursive method
}
You are storing the result but not deleting it from linked list. You can return result in another variable (pointer : result).
Node* getTail(Node *n,int *result){
//u can even free the memory
if(!n->next)
{
result=n->value;
return NULL;
}
n->next=getTail(n->next,result);
}
or you can do it other way
int getTail(Node *n)
{
if(!n) return 0;
if(n->next)
{
if(!n->next->next)
{
Node *frnode=n->next;
int result=n->next->value;
n->next=NULL;
delete frnode;
return result;
}
getTail(n->next);
}
You are not removing last node in your code, and you leak another (temporary) node here.
To remove last node you have to zero the link in the previous node.
Your code should look like
...
if (n == NULL || n->next == NULL)
throw std::out_of_range("node");
if(n->next->next == NULL)
{
int val = n->next->value;
delete n->next;
n->next = NULL;
return val;
}
else ...
Be aware of the fact that c++ is not a functional language and has no optimizations for tail recursion, so in real application as your lists grow big enough you'll eventually have failure with stack overflow =) use Haskell or Erlang for this style of programming, in c++ use for or while.
You should set the Node n's previous Node's next field to NULL when n is the tail Node.

Simple C++ Linked List

I have plenty of previous experience with linked lists in Java, but I seem to have confused myself with this simple attempt in C++. I am getting a segmentation fault at runtime, which from what I understand has to do with assigning a null pointer, but I am at a loss for a solution.
Edit: Thank you all for the very helpful responses. The code is now working, but trying to use delete p; at the end of linkedList::addNode results in a segmentation fault at runtime. Just curious if anyone knew why that is?
Here is my updated code:
#include <iostream>
using namespace std;
class Node{
public:
int data;
Node * next;
Node(int x){
data = x;
next = NULL;
}
Node(int x, Node * y){
data = x;
next = y;
}
};
class linkedList{
Node *head;
public:
linkedList(){
head = NULL;
}
void addNode(int value){
Node *p;
if(head == NULL)
head = new Node (value, NULL);
else{
p=head;
while(p->next !=NULL)
p=p->next;
p->next = new Node (value, NULL);
}
}
void print(){
Node * p;
p = head;
while(p != NULL){
cout << p->data << "\n";
p = p->next;
}
}
};
int main(void){
linkedList test;
test.addNode(4);
test.addNode(76);
test.addNode(12);
test.print();
return(0);
}
First, in linkedList::addNode method, you have the construction if (head = NULL), which will wind up assigning to head; you want the == operator.
Second, about the line:
head = &(Node (value, NULL));
For somewhat unintuitive reasons, this won't work. You'll get a reference to a Node, but that node will go out of scope as soon as the method ends, and attempts to reference it will lead to a segmentation fault. You need to use the new operator (same with the other similar line):
head = new Node(value, NULL);
If you add a method for removing a node, make sure to delete the node then—it won't get automatically garbage-collected like it will in Java.
Sidebar: Think of what happens like this: when you do Node(value, NULL), you're using a temporary variable that's declared like this:
Node hiddenTempNode(value, NULL);
This doesn't allocate space for an object anywhere except on the stack—it's very similar to allocating space for an int and a Node * on the stack as separate variables. As a result, as soon as you leave the method, the object disappears and the pointer to it will do weird things when used.
Third, beware: you may want to set next = NULL in your single-parameter constructor, to ensure that it always has a value. Similarly for your default constructor.
Fourth: your linkedList::print method is looping until p->next is NULL and printing the value of p->next; those occurrences of p->next should probably be changed to just p if you want to get the first and last items.
you are taking the address of variables on the stack
head = &(Node (value, NULL));
should be changed to
head = new Node(value, NULL);
same for the p->next code. Then you will want to delete these nodes in your destructor.
As for the printing try
while(p != NULL)
{
cout << p->data << "\n";
p = p->next;
}
You are allocating space for nodes on stack and grabbing its address, which will go away as soon as the block ends and consequently, the address will be rendered invalid. You should allocate nodes using new operator on the heap instead:
Node* node = new Node(value, NULL);
You should free everything you allocate on the heap as soon as you don't need it to prevent memory leak:
delete node;
For starters
if(head = NULL)
is an assignment, not a check for equality. Change it to
if(head == NULL)
Secondly,
head = &(Node (value, NULL));
Doesn't make sense* change this to
head = new Node (value, NULL);
*this actually creates a temporary object, gives you the address, then destroys that newly created object.
Thirdly,
Node(int x) { data = x; }
Leave next without a value, change this line to
Node(int x) { data = x; next = NULL; }
You are not allocating memory.You should use new to allocate it.
One more error in if(head = NULL) , it should be if(head == NULL)
void addNode(int value){
Node *p;
if(head == NULL)
head = new Node (value, NULL);
else{
p=head;
while(p->next !=NULL)
p=p->next;
p->next = new Node (value, NULL);
}
}
I'd like to add two issues that were not mentioned, yet:
when you 'new' objects, you must 'delete' them at some point.
all three of your constructors should initialize both member variables.
Your delete statement is not actually doing any cleanup. By the time you call it p==null. If you want to cleanup the list, you will need to implement a separate method to iterate through, and delete each and every node.
Something like this:
void ClearList ()
{
Node * c = head;
Node * n;
while (c != NULL)
{
n = c->next;
delete c;
c = n;
}
}
The code is now working, but trying to
use
delete p;
at the end of linkedList::addNode
results in a segmentation fault at
runtime. Just curious if anyone knew
why that is?
Well this is an issue because the purpose of the add node function was to dynamically allocate a new node at the end of the LinkedList. So you do that correctly, now by putting 'delete p;' you are deleting the newly added node (something I imagine you don't actually want). However, to answer your question which is why this causes a segmentation fault:
You add a node, you tell head to point to this new node. Now you delete this new node without telling head that it should once again point to NULL. Thus next time you add a node, or try to print your list, it will immediately attempt to look at what head is pointing to, which is in fact released (deleted) memory, kaboom?
The correct (or at least one correct) usage of delete in your list is in a destructor, remember in C++ we always want to clean up the dynamic memory that we have allocated, your destructor might look like:
~linkedList()
{
Node* p = head;
while ( p!=NULL )
{
Node* nextNode = p->next;
delete p;
p = nextNode;
}
}
By using a destructor like this you guarantee that your linkedList will be cleaned up appropriately when it goes out of scope, or is deleted.
Solution: Don't implement your own linked list. Use the one supplied by the standard library.