I am facing a problem while coding Linked List implementation in c++. Whenever I am trying to add an element I am getting Segmentation Fault error.
#include <iostream>
class node{
public:
int data;
class node *next;
};
class LinkedList {
public:
node *head;
LinkedList(int num);
void add(int number);
void display();
};
const int null = 0;
LinkedList::LinkedList(int num) {
// TODO Auto-generated constructor stub
std::cout<<"Constructor Called"<<std::endl;
head->data = num;
head->next = null;
std::cout<<"Constructor Call completed"<<std::endl;
}
void LinkedList::add(int num) {
struct node *n=new node;
n->data = num;
n->next = null;
struct node *current = head;
while (current->next != null) {
current = current->next;
}
current->next = n;
}
void LinkedList::display() {
std::cout<<"Display"<<std::endl;
struct node *current = head;
while (current!= null) {
std::cout << current->data << "->";
current = current->next;
}
std::cout << "null"<<std::endl;
}
int main() {
LinkedList l(1);
l.display();
l.add(2);
l.display();
return 0;
}
Please look into the gdb debug logs: node n is not referencing to any memory location. So it could not be initialized. Please let me know in case you require any further information.
Thanks in advance!
struct node *n=new node;
Constructor Called
Constructor Call completed
Breakpoint 1, main () at SampleCPP.cpp:60
60 l.display();
(gdb) s
LinkedList::display (this=0xbffff03c) at SampleCPP.cpp:48
48 std::cout
(gdb) n
51 while (current!= null) {
(gdb) n
52 std::cout data ";
(gdb) n
53 current = current->next;
(gdb) n
51 while (current!= null) {
(gdb) n
55 std::cout null
56 }
(gdb) n
main () at SampleCPP.cpp:61
61 l.add(2);
(gdb) s
LinkedList::add (this=0xbffff03c, num=2) at SampleCPP.cpp:38
38 struct node *n=new node;
(gdb) print n
$2 = (node *) 0x0
(gdb)
You never allocate memory for head. That's your problem.
Allocate it in the constructor:
LinkedList::LinkedList(int num) {
std::cout<<"Constructor Called"<<std::endl;
head = new node; // This is missing!
head->data = num;
head->next = null;
std::cout<<"Constructor Call completed"<<std::endl;
}
and it would be good to free all that memory too before your program finishes..
you are not allocating memory for head; it should be like this
LinkedList::LinkedList(int num) {
// TODO Auto-generated constructor stub
head=new node();
std::cout<<"Constructor Called"<<std::endl;
head->data = num;
head->next = null;
std::cout<<"Constructor Call completed"<<std::endl;
}
With a small modification,
class node{
public:
int data;
class node *next;
node(int num): data(num), next(NULL){}
};
And
LinkedList::LinkedList(int num): head(new node(num)) {
// TODO Auto-generated constructor stub
std::cout<<"Constructor Called"<<std::endl;
//Do sth if you wish
std::cout<<"Constructor Call completed"<<std::endl;
}
This removes some additional complexities. Change where ever you instantiate node with new constructor.
I'd like to suggest the following implementation:
#include <iostream>
using namespace std;
class node
{
private:
int data;
node* next;
public:
// Because of that we store the pointer, default implementations of the
// copying operations are not acceptable -- they can lead to memory leakage.
node(const node&) = delete;
node& operator =(const node&) = delete;
node(int d, node* prev = nullptr) :
data(d), next(nullptr)
{
if(prev)
{
// Free memory before assigning the pointer.
delete prev->next;
prev->next = this;
}
}
~node()
{
// Deletes up to the end of the subchain.
delete next;
}
inline node* getNext() const
{
return next;
}
inline operator int() const
{
return data;
}
};
class LinkedList
{
private:
node* head;
node* curr;
public:
LinkedList(int first_entry) :
head(new node(first_entry)), curr(head)
{}
~LinkedList()
{
delete head;
}
void add(int entry)
{
curr = new node(entry, curr);
}
void display() const
{
for(node* i = head; i; i = i->getNext())
cout << (int)*i << "->";
cout << "null" << endl;
}
};
int main(int argc, char* argv[])
{
LinkedList l(1);
l.display();
l.add(2);
l.display();
return EXIT_SUCCESS;
}
In this approach, an additional attention was drawn to the memory management. As well it uses the OOP more intensively.
Related
ok, I created a linked list using the Node class and List class. But whenever I run it using the List object, it throws an exception when I return the head in the getHead() function in Node.cpp
these are the files that I created please if anyone could know why this exception is coming it would be a blessing
//**NODE.h**
#include<iostream>
using namespace std;
class Node{
private:
Node* head;
int data;
public:
Node();
Node(int); //insert data
void setHead(Node*);
Node* getHead();
void setData(int);
int getData();
void printData(Node*);
};
//**Node.cpp**
#include"Node.h"
Node::Node(){
//Node* head = new Node();
head = NULL;
data = 0;
}
Node::Node(int DATA){
//Node* head = new Node();
head = nullptr;
data = DATA;
}
int Node::getData(){ //DATA SETTER
return this->data;
}
void Node::setData(int DATA){ //DATA GETTER
this->data = DATA;
}
Node* Node::getHead(){
return head;
}
void Node::setHead(Node* NextAddress){
this->head = NextAddress;
}
void Node::printData(Node* node){
while(node != nullptr){
cout<< this->data <<"\n";
node = node->head;
}
}
//**List.h**
#include"Node.h"
class List : public Node{
private:
Node* head;
Node* current;
Node* prevcurrent;
public:
List();
//void setList(int);
void insertAtBack(Node* , int);
void insertAtFront(Node* , int);
bool search(int);
void print();
~List();
};
//**List.cpp**
#include"List.h"
List::List(){
head=nullptr;
current=nullptr;
prevcurrent=nullptr;
}
void List::insertAtBack(Node* head , int Data){
Node* newNode = new Node();
newNode->setData(Data);
newNode->setHead(head); //sets the address of the next node into the newly added node
head = newNode;
}
void List::insertAtFront(Node* head, int Data) {
Node* temp = new Node();
}
bool List::search(int num){
Node* temp = head;
while (temp->getHead()!=nullptr)
{
if (temp->getData() == num)
{
return true;
}
temp->setHead(temp->getHead()); //itereates the adress in the emp node to store the address of the next node fro the while loop
}
}
void List::print(){
Node* temp=head;
while (temp->getHead() != nullptr)
{
cout<<temp->getData()<<" ";
}
}
List::~List() {
Node* temp = head;
while (temp->getHead() != nullptr)
{
Node* temp2 = temp;
temp = temp->getHead();
delete temp2;
}
}
//**main.cpp**
#include"List.h"
int main(){
// cout<<"running\n";
// Node box(5); this works
// cout<<box.getData();
List obj;
Node node; //this will throw an exception
obj.insertAtBack(&node,5);
obj.print();
}
Exception is thrown due to print:
void List::print() {
Node *temp = head;
while (temp->getHead() != nullptr) {
cout << temp->getData() << " ";
}
}
Here, a check is missing if temp (or equally head) is a nullptr before you dereference it in temp->getHead()
Same on List::~List
I have written the following link list append, prepend and print methods for LinkedList:
class Node {
public:
int data;
Node *next;
Node(int data) {
this->data = data;
}
};
class LinkedList {
private:
Node *header;
Node *tail;
int size;
public:
LinkedList() {
header = NULL;
tail = NULL;
size = 0;
}
int getSize() {
return size;
}
void append(int data) {
Node *n = new Node(data);
if (header == NULL) {
header = n;
tail = n;
}
else {
tail->next = n;
tail = n;
}
size++;
}
void prepend(int data) {
Node *n = new Node(data);
if (header == NULL) {
header = n;
tail = n;
}
else {
Node *temp = header;
header = n;
n->next = temp;
}
size++;
}
void toString() {
Node *temp = header;
while (temp != NULL) {
cout << temp->data << " ";
temp = temp->next;
}
cout << endl;
}
};
int main()
{
LinkedList list;
list.append(1);
list.append(2);
list.append(3);
list.toString();
return 0;
}
But the program is giving bad access after reaching the last node while printing the list. What is the problem with this code? Can anyone please explain on this?
append() is not initializing the n->next member to NULL. You should do that initialization in Node's constructor, eg:
class Node {
public:
int data;
Node *next;
Node(int data) {
this->data = data;
this->next = NULL; // <-- add this!
}
};
Alternatively:
class Node {
public:
int data;
Node *next = nullptr;
Node(int data) : data(data) {}
};
Or:
class Node {
public:
int data;
Node *next;
Node(int data, Node *next = nullptr) : data(data), next(next) {}
};
That being said, your LinkedList is leaking nodes. You need to add a destructor to free the nodes. You should also add a copy constructor and a copy assignment operator, per the Rule of 3. And in C++11 and later, add a move constructor and a move assignment operator, per the Rule of 5.
Try this:
class Node {
public:
int data;
Node *next;
Node(int data, Node *next = nullptr) : data(data), next(next) {}
};
class LinkedList {
private:
Node *header = nullptr;
Node *tail = nullptr;
int size = 0;
public:
LinkedList() = default;
LinkedList(const LinkedList &src) : LinkedList() {
Node *temp = src.header;
while (temp) {
append(temp->data);
temp = temp->next;
}
}
LinkedList(LinkedList &&src) : LinkedList() {
std::swap(header, src.header);
std::swap(tail, src.tail);
std::swap(size, src.size);
}
~LinkedList() {
Node *temp = header;
while (temp) {
Node *n = temp->next;
delete temp;
temp = n;
}
}
LinkedList& operator=(LinkedList src) {
std::swap(header, src.header);
std::swap(tail, src.tail);
std::swap(size, src.size);
return *this;
}
int getSize() const {
return size;
}
void append(int data) {
Node **temp = (tail) ? &(tail->next) : &header;
*temp = new Node(data);
tail = *temp;
++size;
}
void prepend(int data) {
header = new Node(data, header);
if (!tail) tail = header;
++size;
}
void toString() const {
Node *temp = header;
while (temp) {
cout << temp->data << " ";
temp = temp->next;
}
cout << endl;
}
};
int main()
{
LinkedList list;
list.append(1);
list.append(2);
list.append(3);
list.toString();
return 0;
}
You should always initialize the members of your class.
Node(int data)
: data(data)
, next(nullptr)
{
}
You've forgotten to assign n->next in append(). I suggest that you add an argument to your Node constructor to not forget that:
class Node {
public:
int data;
Node *next;
// make the constructor initialize both "data" and "next"
Node(int data, Node* next) :
data(data),
next(next)
{}
};
With that, your append() and prepend() functions would have to supply the next node upon construction, making mistakes like this a little harder:
void append(int data) {
Node *n = new Node(data, nullptr);
if (header == nullptr) header = n;
else tail->next = n;
tail = n;
++size;
}
void prepend(int data) {
Node *n = new Node(data, header);
if (header == nullptr) tail = n;
header = n;
++size;
}
You also need to add a destructor to delete all the nodes to not leak memory.
I'm writing my own linked list class (for educational purposes) and here it is:
My code
#include <iostream>
using namespace std;
#define PRINT(x) #x << " = " << x << " "
struct ListNode {
int val;
ListNode* next = nullptr;
ListNode(int x) : val(x), next(nullptr) {}
};
class LinkedList {
private:
ListNode* _head;
unsigned long long int _size;
public:
LinkedList() :_head(nullptr), _size(0) {}
LinkedList(ListNode* _h) :_head(_h), _size(0) {
ListNode* node = _head;
while (node != nullptr) {
_size++;
node = node->next;
}
}
// Copy constructor
LinkedList(const LinkedList& obj) {
ListNode* node = obj._head;
while (node != nullptr) {
this->add(node->val);
node = node->next;
}
}
~LinkedList() {
while (_head != nullptr) {
remove();
}
}
void add(const int& value) {
ListNode* node = new ListNode(value);
node->next = _head;
_head = node;
_size++;
}
int remove() {
int v = _head->val;
ListNode* node = _head;
_head = _head->next;
delete node;
_size--;
return v;
}
void print() {
if (size() == 0) {
cout << "List is empty" << endl;
return;
}
ListNode* node = _head;
while (node->next != nullptr) {
cout << node->val << " -> ";
node = node->next;
}
cout << node->val << endl;
}
unsigned long long int size() { return _size; }
ListNode* head() { return _head; }
};
int main() {
LinkedList L;
L.add(4);
L.add(3);
L.add(2);
L.add(1);
L.print();
LinkedList L2(L);
return 0;
}
The problem is that when I run this code, I get this error: error for object 0x7fff5b8beb80: pointer being freed was not allocated I don't understand why. My logic beyond the copy constructor is simple: I iterate over the list I'm copying, which is obj, and I add a new element to this list, which is the list I'm copying to. Since my add() function creates a new element with, well, new, I can't see where my two lists share an element which I'm trying to delete twice in the destructor. What am I doing wrong?
You forgot to initialize your _head in copy constructor:
// Copy constructor
LinkedList(const LinkedList &obj) {
_head = NULL; // <- Add This
ListNode *node = obj._head;
while (node != nullptr) {
this -> add(node -> val);
node = node -> next;
}
}
class linkedlist{
class listNode{
int data;
listNode* next;
void listNode(int data,listNode* next){
this->data=data;
this->next=next;
}
};
int main(){
// in here I want to creat a listnode, but i dont know how to do it
insert(listNode,5);
}
I need to call the listnode in main() function, I know I can use linkedlist list; and then list.listNode, but I need a node in order to fill in the insert() function.
You can simply create a listNode variable like below
int main(){
linkedlist::listNode aNode(5, NULL);
// or
linkedlist::listNode *pNode = new linkenlist::listNode(5,NULL);
....
}
listNode is a class defined inside linkedList class. This means that you need to enter appropriate namespace before usage of described symbol. Also, you need to call constructor of your desired class. To be honest, you better should read some C++ tutorial, because your example has more errors.
Valid very simple implementation would be:
#include <iostream>
class linkedList {
public:
class listNode {
public:
int data;
listNode* next;
listNode(int data_) : data(data_), next(nullptr) {}
};
linkedList() : head(nullptr), tail(nullptr) {}
void insert(listNode* new_node) {
if (head == tail && tail == nullptr) {
head = tail = new_node;
}
else {
tail->next = new_node;
tail = new_node;
}
}
listNode* getFront() { return head; };
listNode* getBack() { return tail; };
listNode* head;
listNode* tail;
};
int main(){
linkedList list;
list.insert(new linkedList::listNode(5));
list.insert(new linkedList::listNode(6));
list.insert(new linkedList::listNode(7));
std::cout << list.getFront()->data << std::endl; // 5
std::cout << list.getBack()->data << std::endl; // 7
return 0;
}
enter image description here
enter code here
class linkedlist{
public:
class listNode{
public:
int data;
listNode* next;
listNode(int data,listNode* next){
this->data=data;
this->next=next;
}
void printNode(listNode* node,ofstream& outFile){
outFile<<"( "<<node->data<<","<<node<<","<<node->next<<","<<node->next-
>data<<")"<<endl;
}
};
// listNode* listHead;
// listNode* listHead(){
// return new listNode(-9999,NULL);
// }
listNode* findSpot(listNode* listHead,listNode* newNode){
listNode* spot=listHead;
while(spot->next!=NULL && spot->next->data<newNode->data)
spot=spot->next;
return spot;
}
void listInsert(listNode* listHead,listNode* newNode){
listNode* spot=findSpot(listHead,newNode);
newNode->next=spot->next;
spot->next=newNode;
}
void printList(listNode* listHead,ofstream& outFile){
listNode* c=listHead;
outFile<<"listHead -> ";
while(c->next!=NULL){
outFile<<"( "<<c->data<<","<<c<<","<<c->next<<","<<c->next->data<<") -> ";
c=c->next;
}
outFile<<" NULL "<<endl;
}
void constructLL(linkedlist::listNode* listHead,ifstream& inFile,ofstream& outFile2){
int a;
cout<<listHead->data<<endl;
while(inFile>>a){
listNode* newNode=new listNode(a,NULL);
listInsert(listHead,newNode);
printList(listHead,outFile2);
}
}
listNode* findMiddleNode(listNode* listHead,ofstream& outFile2){
listNode* walk1=listHead;
listNode* walk2=listHead;
listHead->printNode(walk1, outFile2);
while(walk2!=NULL && walk2->next!=NULL){
walk1=walk1->next;
walk2=walk2->next->next;
}
return walk1;
}
};
int main(int argc ,char* argv[]) {
ifstream inFile(argv[1]);
ofstream outFile1(argv[2]);
ofstream outFile2(argv[3]);
// linkedlist list;
// list.listHead();
cout<<"123";
linkedlist:: listNode listHead(-9999,NULL);
// list.sethead(-9999);
// listHead=new listNode(-9999,NULL);
// cout<<list.gethead();
constructLL(listHead,inFile,outFile2);
// printList(listHead,outFile1);
// listNode* middleNode=findMiddleNode(listHead,outFile2);
// listHead->printNode(middleNode,outFile1);
inFile.close();
outFile1.close();
outFile2.close();
return 0;
}
I was writing a C++ program to implement a linked list. On compilation it's not giving any error but in the output windows it goes blank and program ended with
list1.exe has
encountered a problem and needs to close.
Debugger response: Program received signal SIGSEGV, Segmentation fault.
Maybe it's because of memory leakage, but I'm not able to figure out the exact bug and how can we fix that. Please what's wrong in the prog and what should be fixed?
Below is the code
//Program to implement linked list
#include <iostream>
#include <cstdlib>
using namespace std;
class Node
{
int data;
Node * next;
public:
Node (){}
int getdata(){return data ;}
void setdata(int a){data=a;}
void setnext(Node* c){next=c;}
Node* getnext(){return next;}
};
class linkedlist
{
Node* head;
public:
linkedlist(){head=NULL;}
void print ();
void push_back(int data);
};
void linkedlist::push_back(int data)
{
Node* newnode= new Node();
if(newnode!=NULL)
{
newnode->setdata(data);
newnode->setnext(NULL);
}
Node* ptr= head;
if(ptr==NULL)
{head=newnode;}
while ((ptr->getnext())!=NULL)
{
ptr=ptr->getnext();
}
ptr->setnext(newnode);
}
void linkedlist::print()
{
Node* ptr=head;
if(ptr==NULL)
{cout<<"null"; return;}
while(ptr!=NULL)
{
cout<<(ptr->getdata())<<" ";
ptr=ptr->getnext();
}
}
int main()
{
linkedlist list;
list.push_back(30);
list.push_back(35);
list.print();
return 0;
}
The main issue is here:
if(ptr==NULL) {head=newnode;}
while ((ptr->getnext())!=NULL)
{
ptr=ptr->getnext();
}
ptr->setnext(newnode);
There's probably meant to be a return; in the if (ptr == NULL) part; as it stands, it sets head = newnode, but then continues to try to access ptr->getnext(), which causes the segfault.
Some answers have suggested setting ptr = head = newnode, but note that the bottom line is ptr->setnext(newnode)—this would cause head->getnext() == head. Infinite list!
For your interest, here's your code:
Formatted nice;
Cleaned up not to use using namespace std; (see the C++ FAQ on this);
Takes advantage of const-correctness;
etc.
Enjoy!
#include <iostream>
#include <stdexcept>
class Node {
int data;
Node *next;
public:
Node(): next(NULL) {}
int getdata() const {
return data;
}
void setdata(int a) {
data = a;
}
Node *getnext() const {
return next;
}
void setnext(Node *c) {
next = c;
}
};
class linkedlist {
Node* head;
public:
linkedlist(): head(NULL) {}
void print() const {
Node *ptr = head;
if (ptr == NULL) {
std::cout << "null";
return;
}
while (ptr != NULL) {
std::cout << ptr->getdata() << " ";
ptr = ptr->getnext();
}
}
void push_back(int data) {
Node *newnode = new Node();
if (newnode == NULL) {
throw std::runtime_error("out of memory!");
}
newnode->setdata(data);
Node *ptr = head;
if (ptr == NULL) {
head = newnode;
return;
}
while ((ptr->getnext()) != NULL) {
ptr = ptr->getnext();
}
ptr->setnext(newnode);
}
};
int main() {
linkedlist list;
list.push_back(30);
list.push_back(35);
list.print();
return 0;
}
In the following line: while ((ptr->getnext())!=NULL) ptr is NULL
The push_back code is incorrect, and I've seen some other parts of your code that can be improved:
#include <iostream>
#include<cstdlib>
using namespace std;
class Node
{
int data;
Node * next;
public:
Node(int d = 0) : data(d), next(NULL) {}
int getdata() { return data; }
void setdata(int a) { data = a; }
void setnext(Node* c) { next = c; }
Node* getnext() { return next; }
};
class linkedlist
{
Node* head;
public:
linkedlist() : head(NULL) {}
void print ();
void push_back(int data);
};
void linkedlist::push_back(int data)
{
Node* newnode = new Node(data);
if(head == NULL)
{
head = newnode;
}
else
{
Node* last = head;
while(last->getnext() != NULL)
last = last->getnext();
last->setnext(newnode);
}
}
void linkedlist::print()
{
Node* ptr = head;
if(!ptr)
{
cout << "null";
return;
}
while(ptr != NULL)
{
cout << ptr->getdata() << " ";
ptr=ptr->getnext();
}
}
int main()
{
linkedlist list;
list.push_back(30);
list.push_back(35);
list.print();
return 0;
}
There are still some points to be improved...