Segmentation fault when creating linked list with function - c++

I am trying to create a linked list and then echo the node values to the console. But using a function outside the main function and calling it is causing segmentation fault(core dumped). I can't figure it out why.
The following code works :
#include<iostream>
using std::cout;
using std::endl;
struct node
{
int val;
node* next;
};
void printList(node* start)
{
node* temp;
temp = start;
int i = 0;
while(temp->next != NULL)
{
cout<<"The value in the "<<i<<"th node is : "<<temp->val<<endl;
temp = temp->next;
i++;
}
}
int main()
{
node* start;
node* temp;
start = new node;
temp = start;
for(int i = 0; i < 10; i++)
{
temp->val = i*10;
temp->next = new node;
temp = temp->next;
}
temp->val = 0;
temp->next = NULL;
printList(start);
return 0;
}
But this throws a segmentation fault
#include<iostream>
using std::cout;
using std::endl;
struct node
{
int val;
node* next;
};
void createList(node* start)
{
node* temp;
start = new node;
temp = start;
for(int i = 0; i < 10; i++)
{
temp->val = i*10;
temp->next = new node;
temp = temp->next;
}
temp->val = 0;
temp->next = NULL;
}
void printList(node* start)
{
node* temp;
temp = start;
int i = 0;
while(temp->next != NULL)
{
cout<<"The value in the "<<i<<"th node is : "<<temp->val<<endl;
temp = temp->next;
i++;
}
}
int main()
{
node* start;
createList(start);
printList(start);
return 0;
}

Change void createList(node* start) to void createList(node*& start). (See it work).
In C++, unless specified otherwise, everything is passed by value. In this case, you're passing a pointer to a node (start) to createList by value. You can alter the node it points to (start->...), but not the pointer itself, as you're working with a copy.
Passing the pointer by reference allows you to change the pointer itself.

You're passing the start parameter into the function createList by value, which means that when you do
start = new node;
the copy of start is being assigned the address of the new node. This means that the start variable that you declare in main does not receive the address of the node.
To fix this, use a pointer reference. Pass start to createList by reference, instead of by value. Like this:
void createList(node*& start)
When you pass-by-reference, you're changing the pointer you declared in main directly, rather than creating a copy.

Related

Why does my code stop running when it comes to pointers?

I need to make a simple program with linked lists but my code just stops running.
Down below are to codes, first is the main .cpp file, and the second is header where the problematic function is defined. The code stops when it comes to assigning "new_" pointer attributes (marked with arrows). The function, as its name says, need to generate a linked list from an array, and return the head of that list.
I am using dev c++ for compiling, and he is not throwing any error or warning.
<main.cpp>
#include<stdio.h>
#include"LinkedList2.h"
int main(){
node *head;
int A[] = {2,8,12,9,7};
int n = sizeof(A) / sizeof(A[0]);
head = CreateListFromArray(A, n);
PrintList(head);
return 0;
}
<LinkedList2.h>
#include<stdio.h>
typedef struct node_{
int x;
struct node_ *next;
}node;
node* CreateListFromArray(int A[], int n){
node *head = NULL, *tmp = head, *new_;
for(int i = 0; i < n; i++){
new_->next = NULL; // <------
new_->x = A[I]; // <------
tmp->next = new_;
tmp = tmp->next;
}
return head;
}
void PrintList(node *head){
for(node *tmp = head; tmp != NULL; tmp = tmp->next) printf("%d ", tmp->x);
}
you need to allocate memory for each new node
node* CreateListFromArray(int A[], int n){
node *head = NULL, *tmp = head;
for(int i = 0; i < n; i++){
node *new_ = new node():
new_->next = NULL; // <------
new_->x = A[I]; // <------
tmp->next = new_;
tmp = tmp->next;
}
return head;
}
you also dont have a valid head pointer either, i leave that for you to sort out
note in c++ you dont need typedef any more.
you also have to change A[I] to A[i], because I doesn't exist

All of nodes in linkedlist are the same, seems insertion is not working

I have a linked list in C++, after inserting several nodes now I see that all of them are the same, although I'm using different values to add to node each time, but it's like all of them are the same, even when trying to change a node all of them are changing together or it's the same node that is always being returned, I don't know.
class node
{
public:
int ochance = 3;
string question;
string option1;
int peopleeffectop1;
int courteffectop1;
int treasuryeffectop1;
string option2;
int peopleeffectop2;
int courteffectop2;
int treasuryeffectop2;
node *next;
};
class list
{
private:
node *head, *tail;
public:
list()
{
head=NULL;
tail=NULL;
}
void createnode(int value , string q , string ans1 , int ans1ef1 , int ans1ef2, int ans1ef3 , string ans2, int ans2ef1 , int ans2ef2, int ans2ef3 )
{
node *temp = new node;
temp->ochance = value;
temp->question = q;
temp->option1 = ans1;
temp->peopleeffectop1 = ans1ef1;
temp->courteffectop1 = ans1ef2;
temp->treasuryeffectop1 = ans1ef3;
temp->option2 = ans2;
temp->peopleeffectop2 = ans2ef1;
temp->courteffectop2 = ans2ef2;
temp->treasuryeffectop2 = ans2ef3;
temp->next = NULL;
if(head == NULL)
{
head = temp;
tail = temp;
temp = NULL;
}
else
{
tail->next = temp;
tail = temp;
}
}
node getnth(int pos)
{
node* tmp = new node;
tmp = head;
int i = 0;
while(tmp!=NULL)
{
if (i=pos)
{
return *tmp;
}
i++;
tmp = tmp->next;
}
}
int getlen()
{
node* tmp = new node;
tmp = head;
int i = 0;
while(tmp!=NULL)
{
i++;
tmp = tmp->next;
}
return i;
}
void minus(int pos)
{
node* tmp = new node;
tmp = head;
int i = 0;
while(tmp!=NULL)
{
if (i=pos)
{
tmp->ochance -=1;
}
i++;
tmp = tmp->next;
}
}
void delete_first()
{
node *temp = new node;
temp = head;
head = head->next;
delete temp;
}
void delete_last()
{
node *current = new node;
node *previous = new node;
current = head;
while(current->next != NULL)
{
previous = current;
current = current->next;
}
tail = previous;
previous->next = NULL;
delete current;
}
void delete_position(int pos)
{
node *current = new node;
node *previous = new node;
current = head;
for(int i = 1; i < pos; i++)
{
previous = current;
current = current->next;
}
previous->next = current->next;
}
};
For starters many member functions has a memory leak as for example in this function
node getnth(int pos)
{
node* tmp = new node;
tmp= head;
//
At first memory was allocated and its address was stored in the pointer tmp and then the pointer is reassigned. As a result the address of the allocated memory is lost and the memory is not deleted.
These statements
node* tmp = new node;
tmp= head;
must be substituted for this one statement
node* tmp = head;
Moreover this function
node getnth(int pos)
{
node* tmp = new node;
tmp= head;
int i =0 ;
while(tmp!=NULL){
if (i=pos) {
return *tmp;
}
i++;
tmp = tmp->next;
}
}
has undefined behavior in case when pos is higher than there are nodes in the list. In this case the function returns nothing.
In the function minus there is used the assignment operator instead of the comparison operator
while(tmp!=NULL){
if (i=pos) {
^^^^^
In this function
void delete_first()
{
node *temp=new node;
temp=head;
head=head->next;
delete temp;
}
there is no check whether head is equal to NULL and tail is not adjusted if it is point to the first node.
The same problems are also in the function delete_last only that instead of the adjacent of the tail node as in the previous function you have to adjust the head node.
This function delete_position has the same drawbacks as the previous functions but also it has a bug in the loop
for(int i=1;i<pos;i++)
A node at position 1 will never be deleted.

Creating Linked List using For Loop (c++)

I was trying to create a linked list using a for loop but the 'new' in the for loop in the create() method didn't quite allocate a new slot to store new data. As a result, when I tried to print the list, I got an infinite loop. Can somebody tell me what's wrong here?
struct node
{
double value;
node * next_ptr;
node(){}
node(double val, node * p): value(val), next_ptr(p) {}
~node(){}
};
node * create()
{
using namespace std;
node temp = {0, nullptr};
node * result;
for(int i=1; i<5; ++i)
{
result = new node;
result->value = i;
result->next_ptr = &temp;
temp = *result;
}
return result;
};
The reason you are probably getting an infinite loop is because in:
temp = *result;
you are copying the value of *result into a new object of type node, which is unrelated to the one you created.
What you want to do is store a pointer instead:
node* temp = nullptr;
node* result;
for(int i=0; i<5; ++i)
{
result = new node;
result->value = i;
result->next_ptr = temp;
temp = result;
}
return result;
Live demo
A part from the learning value, just stick to std::forward_list or std::list, for lists, instead. Or even better just use std::vector or other containers (depending on the use that you make of the container).
a simple one to create linked in for loop
#include <iostream>
class LinkedList {
public:
int value;
LinkedList * next;
};
int main()
{
LinkedList *List = nullptr;
LinkedList *head = List;
LinkedList *prev;
for (int i=0; i< 3;i++)
{
LinkedList *temp = new(LinkedList);
temp->value = i;
temp->next = nullptr;
if (head == nullptr)
{
head = temp;
prev = head;
}
else
{
prev->next = temp;
prev = temp;
}
}
}

After exiting from function, nodes aren't saved

My program should create a linked list and show it. My problem is when the addelemnt_end function ends, it doesn't update head and last.
I tried with debug and when my function is done, the info and next part from head and last are "unable to read memory".
struct node{
int info;
node *next;
};
node *head, *last;
void addelement_end(node *head, node *last, int element)
{if (head == NULL)
{ node *temp = new node;
temp->info = element;
temp->next = NULL;
last = temp;
head = temp;
}
else {node*temp = new node;
last->next = temp;
temp->info = element;
temp->next = NULL;
last = temp;
}
}
void show(node* head, node *last)
{
if (head==NULL)
cout << "Empty list";
else
while (head != NULL)
{
cout << head->info << " ";
head = head->next;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int x, n, i;
cout << "how many numbers";
cin >> n;
head = last = NULL;
for (i =1; i <= n; i++)
{
cin >> x;
addelement_end(head, last, x);
}
show(head, last);
return 0;
}
It's a very common error. Here is a similar illustration of the problem:
int change_a(int a) {
a = 42;
}
int main() {
int a = 10;
change_a(a);
printf("%d\n", a);
return 0;
}
This will print 10 because in the function change_a you are only modifying a copy of the value contained in the variable a.
The correct solution is passing a pointer (or using a reference since you are using C++).
int change_a(int *a) {
*a = 42;
}
int main() {
int a = 10;
change_a(&a);
printf("%d\n", a);
return 0;
}
But maybe you're going to tell me: "I'm already using a pointer!". Yes, but a pointer is just a variable. If you want to change where the pointer points, you need to pass a pointer to that pointer.
So, try this:
void addelement_end(node **head, node **last, int element)
{
if (*head == NULL)
{ node *temp = new node;
temp->info = element;
temp->next = NULL;
*last = temp;
*head = temp;
}
else {
node *temp = new node;
(*last)->next = temp;
temp->info = element;
temp->next = NULL;
*last = temp;
}
}

Weird segmentation fault that disappears on using cout

I'm trying out a basic program that will randomly initialize a linked list and print the value at a user-specified index (getnth). However, I'm running into a weird segmentation fault that appears when I comment out a specific cout line, and disappears when I uncomment it.
#include<iostream>
#include<cstdlib>
using namespace std;
struct node
{
int x;
node *next;
};
void ins(struct node*& headRef, int n)
{
node *newNode = new node;
if (!newNode)
return;
newNode->x = n;
if (!headRef)
newNode->next = NULL;
else
newNode->next = headRef;
headRef = newNode;
cout<<"\n"<<n<<" inserted at "<<headRef<<"\n\n";
}
void disp(struct node* head)
{
node *temp = head;
if (!temp)
{
cout<<"\n\nLL empty\n";
return;
}
while (temp)
{
cout<<temp->x<<" ";
temp = temp->next;
}
cout<<"\n\n";
}
void getnth(struct node* head, int n)
{
int i=0;
node *temp = head;
while (temp)
{
if (i == n)
{
cout<<"\n"<<temp->x<<"\n\n";
return;
}
}
cout<<"\nIndex too high\n";
}
int main()
{
node *head;
int i;
srand(time(NULL));
for (i=0; i<10; i++)
{
ins(head, rand()%10+1);
cout<<"Main head is "<<head<<"\n"; // segfault appears if this line is commented out, disappears if it's not
}
cout<<"\nInitial LL\n\n";
disp(head);
cout<<"\nEnter index ";
cin>>i;
getnth(head, i);
return 0;
}
In main initialize
node *head=NULL;
and your getnth is wrong , fix it.
May be something like this :-
void getnth(struct node* head, int n)
{
int i=0;
node *temp = head;
while (temp)
{
if (++i == n)
{
cout<<"\n"<<temp->x<<"\n\n";
return;
}
temp=temp->next;
}
cout<<"\nIndex too high\n";
}
By default, the pointer "head" in "main( )" is initialized with garbage, because it's automatic variable allocated on program stack.
So, when you pass the pointer "head" to the function "disp( )", this pointer is dereferenced and it causes segmentation fault.
You have to initialize the pointer "head" with 0 explicitly, and this will fix the problem.