Linked List Segmentation Fault - c++

Why does this cause a SegFault Error? I've tried to run a backtrace with gdb, but it has given me no help.
Any help would be appreciated, I've been pulling my hair out over this for hours.
my node.h
#ifndef NODE_H
#define NODE_H
#include <string>
using namespace std;
class Node
{
public:
Node(const string, const int) ;
~Node() { }
void setNext(Node *);//setter for the next variable
Node * getNext();// getter for the next variable
string getKey();// getter for the key variable
int getDistance(); // getter for the dist variable
private:
Node *next;
int dist;
string key;
};
#endif
My Node.cpp
#include "node.h"
#include <string>
Node::Node(string k, int d){
key = k;
dist = d;
}
void Node::setNext(Node * n){
next = n;
}
Node * Node::getNext(){
return next;
}
string Node::getKey(){
return key;
}
int Node::getDistance(){
return dist;
}
My list.h
#ifndef LIST_H
#define LIST_H
#include "node.h"
class SLL
{
public:
SLL();
~SLL() { }
void Insert (string searchKey, int distance);
bool Delete (string searchKey);
void Print();
int Search(string searchKey);
private:
int count;
Node *head;
Node *iterator;
Node *temp;
};
#endif
my List.cpp
#include "list.h"
#include <iostream>
SLL::SLL():head(0){}
void SLL::Insert(string searchKey, int distance){
Node * temp = new Node(searchKey, distance);
if(head == 0){
head = temp;
}
else{
temp->setNext(head);
head = temp;
}
}
bool SLL::Delete(string searchKey){
if(head == 0){
cout << "An attempt was made to delete a node from an empty list" << endl;
}
else{
Node* iterator = head;
Node* last = 0;
while(iterator != 0){
if (iterator->getKey() == searchKey){
break;
}
else{
last = iterator;
iterator = iterator->getNext();
}
}
if (iterator == 0){
return false;
}
else{
if(head == iterator){
head = head->getNext();
}
else {
last->setNext(iterator->getNext());
}
delete iterator;
}
}
}
void SLL:: Print(){
iterator = head;
while(iterator != 0){
cout << iterator->getKey() << "-" << iterator->getDistance() << endl;
iterator = iterator->getNext();
}
}
int SLL::Search(string searchKey){
}
My main.cpp
#include "list.h"
#include "node.h"
#include <iostream>
using namespace std;
int main(int argc, char* argv[]) {
SLL * sll;
sll->Insert("test", 1);
sll->Insert("test2", 2);
sll->Delete("test");
sll->Print();
}

Hint: Segfault happens here:
int main(int argc, char* argv[]) {
SLL * sll;
sll->Insert("test", 1); // BIG segfault here.
...
(No full answers as this looks like homework.)

In your main function, the pointer to SSL is not initialised, but you dereference it. This is undefined behaviour. In your particular case, this is causing a segmentation violation. Try changing you code to create a SSL object, either on the stack:
int main(int argc, char* argv[]) {
SLL sll;
sll.Insert("test", 1);
// ...
}
or the heap:
int main(int argc, char* argv[]) {
SLL * sll = new SLL();
sll->Insert("test", 1);
// ...
}
BTW, you are never using the temp, iterator, ... fields of the SLL class, never initialise them. In your implementation, you define local variables that hide them, so I'd suggest removing the fields or initialising them in the constructor.

Related

Why does my Template Linked List not work?

I can't specify what the problem is nor do I get any errors. This is my code:
Node.h:
#ifndef NODE_H
#define NODE_H
#include <iostream>
using namespace std;
template <typename T>
class LinkedList;
template <typename T>
class Node {
public:
Node(T data) : data(data),previousNode(nullptr),nextNode(nullptr) {}
Node<T>* GetNextNode() const {
return nextNode;
}
void SetNextNode(Node<T>* nextNode) {
this->nextNode = nextNode;
}
Node<T>* GetPreviousNode() const {
return previousNode;
}
void SetPreviousNode(Node<T>* previousNode) {
this->previousNode = previousNode;
}
T GetData() const {
return data;
}
void SetData(T data) {
this->data = data;
}
private:
T data;
Node<T>* previousNode;
Node<T>* nextNode;
};
#endif /* NODE_H */
linkedList.h:
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include "node.h"
#include <stdexcept>
#include <iostream>
#include <booking.h>
using namespace std;
template<typename T>
class LinkedList {
public:
LinkedList() {
root = nullptr;
end = nullptr;
cursor = end;
}
void insertNode(T data) {
Node<T>* node = new Node<T>(data);
cerr << "entered insert node" << endl;
if (root == nullptr) {
root = node;
node->SetNextNode(end);
end->SetPreviousNode(node);
}else{
node->SetNextNode(cursor);
node->SetPreviousNode(cursor->GetPreviousNode());
if (cursor->GetPreviousNode())
cursor->GetPreviousNode()->SetNextNode(node);
cursor->SetPreviousNode(node);
}
cursor = node;
if (!cursor->GetPreviousNode())
root = cursor;
}
bool isAtEnd() {
return (cursor == end);
};
void step_back() {
if (cursor && cursor->GetPreviousNode()) {
cursor = cursor->GetPreviousNode();
}
}
void advance() {
if (cursor && cursor->GetNextNode()) {
cursor = cursor->GetNextNode(); }
};
T getNode() {
return cursor->GetData();
};
void reset() {
cursor = root;
};
void deleteNode() {
Node<T>* tmpPrevious;
Node<T>* tmpNext;
if (root == nullptr) {
throw underflow_error("empty list...");
} else {
if (cursor->GetPreviousNode() == nullptr) {
if (cursor->GetNextNode() == end) {
delete cursor;
root = nullptr;
end->SetPreviousNode(nullptr);
cursor = end;
} else {
cursor = cursor->GetNextNode();
delete (root);
cursor->SetPreviousNode(nullptr);
root = cursor;
}
} else {
if (cursor->GetNextNode() == end) {
tmpPrevious = cursor->GetPreviousNode();
delete cursor;
cursor = end;
end->SetPreviousNode(tmpPrevious);
tmpPrevious->SetNextNode(end);
} else {
tmpPrevious = cursor->GetPreviousNode();
tmpNext = cursor->GetNextNode();
delete cursor;
tmpPrevious->SetNextNode(tmpNext);
tmpNext->SetPreviousNode(tmpPrevious);
cursor = tmpNext;
}
}
}
return;
};
protected:
Node<T>* root;
Node<T>* cursor;
Node<T>* end;
};
#endif /* LINKEDLIST_H */
Booking.h
#ifndef BOOKING_H
#define BOOKING_H
class Booking{
private:
long bookingID;
public:
Booking(long bookingID);
long getBookingID();
};
#endif // BOOKING_H
Booking.ccp:
#include "booking.h"
Booking::Booking(long bookingID):bookingID(bookingID){}
long Booking::getBookingID(){
return bookingID;
}
main.cpp:
#include <QCoreApplication>
#include <cstdlib>
#include <linkedList.h>
#include <iostream>
#include <string>
#include <booking.h>
using namespace std;
int main(int argc, char *argv[]){
QCoreApplication a(argc, argv);
LinkedList<Booking*> allBookings;
Booking* booking1 = new Booking(12);
allBookings.insertNode(booking1);
long test = allBookings.getNode()->getBookingID();
cout << "test: " << test << endl; //doesn't print anything
return a.exec();
}
I didn't get any errors. cout << "test: " << test << endl; in the main.cpp doesn't execute, because I was expecting it to print something. What am I doing wrong here? I did some debugging and I think in my Node.h implementation the function SetPreviousNode doesn't execute when I'm trying to insert a node in the main.cpp.
This code in insertNode
if (root == nullptr) {
root = node;
node->SetNextNode(end);
end->SetPreviousNode(node);
}else{
end has a value of nullptr at when you reach end->SetPreviousNode(node); which is likely crashing your program. (You should be able to confirm that in your debugger).
I'd like to suggest a fix but it's not clear to me what you are trying to do. The code seems a little complex. Plus I don't like the design decision to include a cursor in the list. I would drop that if you are able to.

Find all matching nodes in linked list c++ [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I'm writing a function to find all occurrences of a node in a linked list, the function will return the number of occurrences to the main function which will then display those occurrences. The program does compile but the it just freezes and nothing seems to happen when I enter the correct name to look for, if I enter the wrong name, which is not in the list, the findall function returns 0 and the rest of the program works fine. Please take a look.
main.cpp
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
#include "List.h"
void extra(list &);
/***********************************
* Main
* Test function - DO NOT CHANGE
***********************************/
void main()
{
list a;
extra(a);
}
/***********************************
* Extra Credit
* Test function - DO NOT CHANGE
***********************************/
void extra(list &a)
{ int i,n;
node_ptr map[4];
string first,last;
// Find node
cout << endl;
cout << "Enter First and Last name: ";
cin >> first >> last;
n = a.findall(first,last,map,4);
// Display forwards
cout << endl;
cout << "Find List\n--------------\n";
for (i = 0; i < n; i++)
{
map[i]->put(cout);
}
}
List.h
#include "Node.h"
#include <iostream>
#include <string>
using namespace std;
class list
{ public:
list(); // Empty constructor
~list(); // Destructor
int findall(string, string, node_ptr*, int);
node *find(string, string); // Locate a note
private:
node *head;
};
Node.h
#include <iostream>
#include <string>
using namespace std;
class list;
class node
{ friend list;
public:
node(); // Null constructor
~node(); // Destructor
void put(ostream &out); // Put
private:
string first,last;
int age;
node *next;
};
typedef node * node_ptr;
List.cpp
#include "List.h"
#include <iostream>
#include <string>
using namespace std;
/**
* Empty Constructor
*
*/
list::list()
{
head = nullptr;
}
/**
* Destructor Constructor
*
*/
list::~list()
{ if (head == nullptr) return;
node *p = head, *t;
while (p)
{
t = p;
p = p->next;
delete t;
}
head = nullptr;
}
/**
* Locate node
*
*/
node *list::find(string last, string first)
{
node *temp = head;
while (temp)
{
if (temp->first == first && temp->last == last) return temp;
temp = temp->next;
}
return nullptr;
}
/**
* Find all.
*
*/
int list::findall(string first, string last, node_ptr* map, int n)
{
int ans;
ans = 0;
*map = find(first, last);
while (*map != NULL)
{
ans++;
*map = (*map)->next;
*map = find(first, last);
}
return ans;
}
Node.cpp
#include "Node.h"
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
/**
* Empty Constructor
*
*/
node::node()
{
last = "";
first = "";
age = 0;
next = nullptr;
}
/**
* Destructor
*
*/
node::~node()
{ if (next != nullptr) next = nullptr;
}
/**
* Put
*
*/
void node::put(ostream &out)
{ out << setw(14) << left << last << setw(14) << first << setw(10) << age << endl;
}
I really appreciate your help. Thank you.
findall() freezes because it gets stuck in an endless loop.
If no matching node is found, the first call to find() returns nullptr and findall() exits.
But if a matching node is found, a loop is entered, calling find() to search the entire list all over again from the beginning. That will find the same node as before. Then you call find() again, and again, and so on.
To solve this issue, if find() returns a matching node, you need to pass the next node in the following call to find() so it can start searching where the previous search left off. Repeat until you reach the end of the list.
class list
{ public:
...
int findall(string first, string last, node_ptr *map, int n);
node_ptr find(string first, string last, node_ptr start = nullptr); // Locate a note
...
};
node_ptr list::find(string last, string first, node_ptr start)
{
node_ptr temp = (start) ? start : head;
while (temp)
{
if ((temp->first == first) && (temp->last == last)) break;
temp = temp->next;
}
return temp;
}
int list::findall(string first, string last, node_ptr* map, int n)
{
int ans = 0;
node_ptr temp = nullptr;
while (ans < n)
{
temp = find(first, last, temp);
if (!temp) break;
*map++ = temp;
++ans;
temp = temp->next;
}
return ans;
}
Update: if you are not able to change the signature of find() then you will have to re-write findall() to duplicate what find() does:
class list
{ public:
...
int findall(string first, string last, node_ptr *map, int n);
node_ptr find(string first, string last); // Locate a node
...
};
node_ptr list::find(string last, string first)
{
node_ptr temp = head;
while (temp)
{
if ((temp->first == first) && (temp->last == last)) break;
temp = temp->next;
}
return temp;
}
int list::findall(string first, string last, node_ptr* map, int n)
{
int ans = 0;
node_ptr temp = head;
while (ans < n)
{
while (temp)
{
if ((temp->first == first) && (temp->last == last)) break;
temp = temp->next;
}
if (!temp) break;
*map++ = temp;
++ans;
temp = temp->next;
}
return ans;
}

C++: Implementing insert function for a linked list, prev_ptr ends up being NULL

node.h:
#ifndef NODE_H
#define NODE_H
#include <iostream>
namespace mdm{
class node{
public:
typedef int value_type;
node(const value_type& init_data = value_type(), node *init_link = NULL){
data = init_data;
link = init_link;
}
void setData(const value_type& newData){
data = newData;
}
void setLink(node *newLink){
link = newLink;
}
value_type getdata() const {
return data;
}
const node *linker() const {
return link;
}
node *linker(){
return link;
}
private:
value_type data;
node *link;
};
}
#endif // !node_h
linked_list.h:
#ifndef linked_list_h
#define linked_list_h
#include <iostream>
#include "node.h"
namespace mdislamwork_at_gmail_com{
class llist{
public:
llist(node *head = NULL){
head_ptr = head;
}
size_t list_length(const node *head_ptr);
void insert(const node::value_type& entry, size_t position);
void remove(node del);
void insert_to_head(node *&head_ptr, const node::value_type &entry);
private:
node *head_ptr;
};
}
#endif // !linked_list.h
linked_list.cpp:
#include <iostream>
#include "linked_list.h"
#include <assert.h>
using namespace std;
namespace mdm{
size_t llist::list_length(const node *head_ptr){
const node *cursor;
size_t count = 0;
for (cursor = head_ptr; cursor != NULL; cursor = cursor->linker()) {
count++;
}
return count;
}
void llist::insert(const node::value_type& entry, size_t position){
node* prev_ptr = head_ptr;
if (list_length(head_ptr) == 0)
insert_to_head(head_ptr, entry);
else{
assert(prev_ptr != NULL);
size_t count = 0;
while (count < position){
prev_ptr = prev_ptr->linker();
count++;
}
}
node *m_head_ptr;
assert(prev_ptr != NULL);
m_head_ptr = prev_ptr->linker();
insert_to_head(m_head_ptr, entry);
prev_ptr->setLink(m_head_ptr);
}
void llist::remove(node del){
}
void llist::insert_to_head(node *&head_ptr, const node::value_type &entry){
head_ptr = new node(entry, head_ptr);
}
}
main.cpp
#include <iostream>
#include "node.h"
#include "linked_list.h"
using namespace std;
using namespace mdm;
int main() {
node *head_ptr = NULL;
llist linked_list(head_ptr);
linked_list.insert_to_head(head_ptr, 44);
cout << linked_list.list_length(head_ptr) << endl;
linked_list.insert_to_head(head_ptr, 49);
cout << linked_list.list_length(head_ptr) << endl;
linked_list.insert(5,2);
//linked_list.insert(5, 2);
cout << linked_list.list_length(head_ptr) << endl;
return 0;
}
I posted the entirety of the code. I am having trouble inserting at an n-th position. For some reason in the insert implementation, the prev_ptr is NULL when it should have the memory address of where the new node will be placed.
Its hard to tell what the problem is what with head_ptr and its operations out of the scope of your posted method. What is head_ptr? A node*? a node? How are your nodes inserted initially? The scope of this method in relation to your problem is hard to understand.
Check to see if the head_ptr variable is null throughout the whole of your program. Is it always null? Does it become null? What other operations for your linked list have you implemented? Do they work ok? Its just really hard to tell what is wrong when you provide one method to an entire implementation.

Not recognizing cout<< in my program?

I'm creating a program with multiple files and it's not recognizing cout<< in my tnode file. Can anyone locate where the problem is? Among other errors, I get this error "cout was not declared in this scope" in my node file.
My main function:
#include <iostream>
#include "bst.h"
using namespace std;
int main(int argc, char *argv[]) {
cout<<"hi";
bst *list = new bst();
return 0;
}
My BinarySearchTree file:
#ifndef bst_H
#define bst_H
#include <iostream>
#include <string>
#include "tnode.h"
class bst
{
public:
bst()
{
root = NULL;
}
void add(int key, char value) {
if (root == NULL) {
root = new tnode(key, value);
return
} else
root->add(key, value);
return
}
tnode *root;
};
#endif
My node file:
#ifndef tnode_H
#define tnode_H
#include <iostream>
#include <string>
class tnode
{
public:
tnode(int key, char value)
{
this->key = key;
this->value = value;
N = 1;
left = NULL;
right = NULL;
cout<<"hi";
}
void add(int key, char value) {
if (key == this->key)
{
cout<<"This key already exists";
return;
}
else if (key < this->key)
{
if (left == NULL)
{
left = new tnode(key, value);
cout<<"Your node has been placed!!";
return;
}
else
{
left->add(key, value);
cout<<"Your node has been placed!";
return;
}
}
else if (key > this->key)
{
if (right == NULL)
{
right = new tnode(key, value);
cout<<"Your node has been placed!!"; return;
}
else
return right->add(key, value);
}
return;
}
tnode* left;
tnode* right;
int key;
char value;
int N;
};
#endif
You need to do :
using namespace std;
or
std::cout
in your tnode file
But using namespace std is considered bad practice, so you'd better use the second way:
std::cout<<"Your node has been placed!!";
You need to use the namespace std. Either by using namespace std (which could go in .cpp files but never in .h files, read more about why here) or by using std::cout when calling it.

I'm building a student list out of a double LL

I'm trying to build a list of students using my double linked list class. I ended up combining my student and Node class together to do this. I realize there are better ways to implement this, but this is the path I chose and i'm trying to get it to work. When I push_back a node (Student), it calls my Node class, which then calls my Record class which then calls my Course class.
When calling my constructor for a node in my main function, i'm hit with the error that none of the strings I pass "(Name, course, semester) was not declared in this scope". I realize this might be a mess, but can anyone give me an idea as to why this isn't working?
#include <iostream>
#include "LinkedList.h"
#include "Stack.h"
#include "Queue.h"
using namespace std;
int main () {
LinkedList* list = new LinkedList();
list->push_back(John, Math34, Summer2012);
return 0;
}
My LinkedList class. I took out most of the functions so it will be easier to read and find the root of the problem.
#ifndef LinkedList_H
#define LinkedList_H
#include "Node.h"
#include <iostream>
using namespace std;
class LinkedList{
public:
LinkedList()
{
front = NULL;
back = NULL;
size = 0;
}
void aCourse(string n, Course* c, string s)
{
if (front == NULL)
return;
Node *temp = front;
for(int i = 0; i < size; i++)
{
if(n == temp->name)
front->addCourse(c, s);
} }
void push_back(string n, Course* c, string s)
{
if (back == NULL)
{
back = new Node(NULL, NULL, n);
front = back;
size++;
back->addCourse(c, s);
return;
}
else {
Node *newnode = new Node(NULL, NULL, n);
newnode->addCourse(c, s);
back->next = newnode;
newnode->prev = back;
back = newnode;
}
#endif
My Node / Student class:
#ifndef NODE_H
#define NODE_H
#include "Record.h"
#include "Course.h"
class Node
{
public:
Node(Node* n = NULL, Node* p = NULL, string v = NULL)
{
prev = p;
next = n;
name = v;
rec = new Record;
}
void addCourse(Course* c, string sem)
{
rec->addCourse(c, sem);
}
void dropCourse(Course* c)
{
rec->dropCourse(c);
}
Record* getRecord() { return rec; }
void printAllRecords()
{
rec->print();
}
void setStudentScore(Course* c, int score)
{
rec->setCourseScore(c, score);
}
string name;
Record* rec;
Node* next;
Node* prev; //for double linked list
char value;
};
#endif
My record class:
#ifndef Record_H
#define Record_H
#include "Course.h"
#include <string>
#include <vector>
#include <iostream>
using namespace std;
class Record
{
public:
Record()
{
courses = new vector<Course*>();
semesters = new vector<string>();
scores = new vector<int>();
}
~Record()
{
delete courses;
delete semesters;
delete scores;
}
void addCourse(Course* c, string sem)
{
courses->push_back(c);
semesters->push_back(sem);
scores->push_back(0);
}
void dropCourse(Course* c)
{
vector<Course*>::iterator it = courses->begin();
vector<string>::iterator it2 = semesters->begin();
while ( it != courses->end() && it2 != semesters->end())
{
if (c == *it)
break;
it++;
it2++;
}
courses->erase(it);
semesters->erase(it2);
}
void setCourseScore(Course* c, int g)
{
vector<Course*>::iterator it = courses->begin();
vector<int>::iterator it2 = scores->begin();
while ( it != courses->end() && it2 != scores->end())
{
if (c == *it)
break;
it++;
it2++;
}
it2 = scores->insert(it2, g);
}
void computeAccGPA()
{
}
vector<Course*>* getCourses() { return courses; }
void print(){
vector<Course*>::iterator it = courses->begin();
vector<string>::iterator it2 = semesters->begin();
vector<int>::iterator it3 = scores->begin();
while ( it != courses->end() && it2 != semesters->end() && it3 != scores->end())
{
(*it)->print();
cout<<" "<<*it2<<" "<<*it3<<endl;
it++;
it2++;
it3++;
}
cout<<endl;
}
private:
vector<Course*>* courses;
vector<string>* semesters;
vector<int>* scores;
};
#endif
My course class:
#ifndef Course_H
#define Course_H
#include <string>
#include <iostream>
using namespace std;
class Course
{
public:
Course(string n, string f, int c)
{
name = n;
faculty = f;
credit =c;
}
~Course() {}
void print()
{
cout<<name<<" "<<faculty<<" ";//<<c<<" ";
}
private:
string name;
string faculty;
int credit;
};
#endif
I think this line list->push_back(John, Math34, Summer2012); is the problem.
You are not passing strings. Replace it with list->push_back("John", new Course("Math (course name)", "Math (faculty)", 34), "Summer2012");