I am writing a generic linked list in C++ using templates, and am experiencing Segmentation Faults when accessing Node values.
To make the test case simpler, I have implemented a fixed size, two node, linked list.
I have two questions:
1a) Why isn't aList.headNodePtr->prevNodePtr set to NULL?
1b) Why isn't aList.tailNodePtr->nextNodePtr set to NULL?
I set both of these values to NULL in the LinkedList constructor, but the output in main shows that:
head prevAddress: 0x89485ed18949ed31
tail nextAddress: 0x7fffe8849679
2) Why does the following line in main() cause a Seg Fault?
aList.headNodePtr->nodeValue = 1;
The full code is below:
#include <iostream>
using namespace std;
template <class T>
class Node {
public:
Node<T>* prevNodePtr;
Node<T>* nextNodePtr;
T nodeValue;
};
template <typename T>
class LinkedList {
public:
Node<T>* headNodePtr;
Node<T>* tailNodePtr;
LinkedList() {
Node<T>* headNodePtr = new Node<T>;
Node<T>* tailNodePtr = new Node<T>;
headNodePtr->prevNodePtr = NULL;
headNodePtr->nextNodePtr = tailNodePtr;
tailNodePtr->prevNodePtr = headNodePtr;
tailNodePtr->nextNodePtr = NULL;
}
~LinkedList() {
headNodePtr = NULL;
tailNodePtr = NULL;
delete headNodePtr;
delete tailNodePtr;
}
};
int main()
{
LinkedList<int> aList;
cout << "head Value: " << aList.headNodePtr->nodeValue << endl;
cout << "head prevAddress: " << aList.headNodePtr->prevNodePtr << endl;
cout << "head nextAddress: " << aList.headNodePtr->nextNodePtr << endl;
cout << "tail Value: " << aList.tailNodePtr->nodeValue << endl;
cout << "tail prevAddress: " << aList.tailNodePtr->prevNodePtr << endl;
cout << "tail nextAddress: " << aList.tailNodePtr->nextNodePtr << endl;
aList.headNodePtr->nodeValue = 1;
}
You're not actually setting the members, you're setting the locals you declared in the ctor:
Node<T>* headNodePtr; // <-- MEMBERS
Node<T>* tailNodePtr;
LinkedList() {
Node<T>* headNodePtr = new Node<T>; // <-- LOCALS
Node<T>* tailNodePtr = new Node<T>;
Try this instead:
Node<T>* headNodePtr; // <-- MEMBERS
Node<T>* tailNodePtr;
LinkedList() {
headNodePtr = new Node<T>; // <-- MEMBER ACCESS
tailNodePtr = new Node<T>;
Related
I am trying to reverse a liked list in c++ but unfortunately I am unable to do that. Here is the entire program I am working on. I don't know where the problem is. The problem I think is either
reverse()
or
displayList()
void reverse()
{
struct node *curr = head;
struct node *next = NULL;
struct node *prev = NULL;
while (curr != NULL)
{
next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
head = prev;
}
void displayList()
{
while (head != NULL)
{
cout << head->data << " ";
head = head->next;
}
cout << endl;
}
int main(){
createNode(100);
createNode(310);
createNode(150);
createNode(300);
createNode(500);
cout << "Original List" << endl;
displayList();
cout << endl << "Reversed List" << endl;
reverse();
displayList();
return 0;
}
When I comment displayList() when I first called it, it worked. Basically the function runs only one time.
Assuming displayList to be a member function of some List type because there is no local variable head anywhere: You destroy your list (leaking all data) when iterating over it in displayList. Here are some fixes.
void displayList() const
{
node* curr = head;
while (curr != nullptr)
{
std::cout << curr->data << ' ';
curr = curr->next;
}
std::cout << '\n';
}
If you get into the habit of making functions const that are not supposed to change the object, your compiler would have spotted this for you.
I'm writing a program about creating a list of country, there seems to no error in my code but when debugging, I get the error: Unhandled exception thrown: Read access violation p was 0xFFFFFFFFFFFFFFFF, after I input some values.
Can anyone give me a hint or find me the mistake?
#include <cstring>
#include <string>
using namespace std;
this is my struct Provice.
struct Province
{
int Code;
string Name;
int Pop;
float Area;
};
struct node
{
struct Province data;
node* next;
};
struct List
{
node* head;
node* tail;
};
void Init(List &l)
{
l.head = NULL;
l.tail = NULL;
}
void add_tail(List& l, node* p)
{
if (l.head == NULL)
{
l.head = p;
l.tail = p;
}
else
{
l.tail->next = p;
l.tail = p;
}
}
I think I got some problem when I create a node here without initializing value, is this right ?
void inputListProvinces(List& l)
{
int n;
cin >> n;
int i = 0;
while(i<n)
{
node* p = new node;
cin >> p->data.Code;
cin.ignore();
getline(cin, p->data.Name);
cin.ignore();
cin >> p->data.Pop;
cin >> p->data.Area;
add_tail(l, p);
i++;
}
}
And the error happens here, but I dont know how to fix.
void outputListProvinces(List& l)
{
node* p = l.head;
while (p != NULL)
{
cout << p->data.Code << '\t'; /*Unhandled exception thrown: read access violation.
p was 0xFFFFFFFFFFFFFFFF*/
cout << p->data.Name << '\t';
cout << p->data.Pop << '\t';
cout << p->data.Area << '\t';
cout << endl;
p = p->next;
}
}
void outputProvince(node* p)
{
cout << p->data.Code << '\t';
cout << p->data.Name << '\t';
cout << p->data.Pop << '\t';
cout << p->data.Area << '\t';
}
void outputProvincesMore1MillionPop(List& l)
{
node* p = l.head;
while (p != NULL)
{
if (p->data.Pop > 1000)
{
outputProvince(p);
cout << endl;
}
p = p->next;
}
}
node* findProMaxArea(List& l)
{
node* n = l.head;
node* p = l.head;
while (p != NULL)
{
if (p->data.Area > n->data.Area)
{
n = p;
}
p = p->next;
}
return n;
}
int main()
{
List L;
Init(L);
inputListProvinces(L);
cout << "List of provinces:" << endl;
cout << "ID\t|Province\t|Population\t|Area" << endl;
outputListProvinces(L);
cout << "Provinces with a population of more than 1 million:" << endl;
outputProvincesMore1MillionPop(L);
cout << "The largest province:" << endl;
node* p = findProMaxArea(L);
if (p) outputProvince(p);
return 0;
}
Mistake is node never initializes its next pointer. You can only count on it being NULL if you set it to NULL, and the last node in the list MUST be NULLor the program can't find the end of the List and marches off into the wacky world of Undefined Behaviour.
Safest Fix: Add a constructor to node to make sure next is always initialized.
struct node
{
struct Province data;
node* next;
node(node* n = NULL): next(n)
{
}
};
There are other fixes, like making sure l.tail->next = NULL; at the end of inputListProvinces, but I don't think it's really worth the reduced overhead given the slow-ness of the console IO.
And if you do that, then you should also roll Init into List as a constructor:
struct List
{
node* head;
node* tail;
List(): head(NULL), tail(NULL)
{
}
};
This should leave you with the problem of a poorly-placed cin.ignore() consuming a character you don't want consumed.
Side note: Replace NULL with nullptr if available to your compiler and target C++ Standard revision. nullptr removes the bugs that can result from NULL being a glorified 0.
class Node {
public:
Node();
void setNext(Node*);
private:
void* item;
Node* next;
};
void Node::setNext(Node* n)
{
next = n;
}
class List {
public:
List();
void addFirst(void*);
void reset();
void* getCurItem();
private:
Node* head;
Node* current;
};
void List::addFirst(void* obj)
{
Node *newNode = new Node(obj);
newNode->setNext(head);
head = newNode;
}
void List::reset()
{
current = head;
}
void* List::getCurItem()
{
return current->getItem();
}
Polynomial::Polynomial(std::ifstream& input){
List *polyCo = new List();
List *polyEx = new List();
bool exit = false;
double coefficient=0;
int exponent=0;
while(!exit && input.good()){
input >> coefficient;
if(coefficient != -9999.99){
input >> exponent;
cout << "Exponent before: " << exponent << endl;
cout << "Coefficient before: " << coefficient << endl;
int *ExPtr = &exponent;
double *CoPtr = &coefficient;
cout << "Exponent: " << *(ExPtr) << endl;
cout << "Coefficient: " << *(CoPtr) << endl;
polyCo->addFirst(ExPtr);
polyEx->addFirst(CoPtr);
cout << polyCo->getCurItem() << endl; //SEG FAULT
}
}
polyEx->reset();
polyCo->reset();
}
I am reading numbers from a file into two separate linked lists. I am getting a segmentation fault when attempting to access the value in either of the linked list.
First, I'm going to outline how I think my addFirst() functions works, because I could just be implementing it incorrectly. When addFirst() is called, a new node is created, and the data being read in is set equal to the member of the new node. The existing node in the list is pushed forward, and the new node created becomes the head. The two nodes are also linked.
There could be something else entirely wrong besides my implementation of the function, but at least it is a good place to start, along with the source of the segmentation fault.
I'm trying to implement a simple linked list. I need an insert function that takes a value and a node to insert after, so I have this:
#include <iostream>
using namespace std;
typedef struct node node;
struct node {
int data;
node * next = NULL;
};
void insert(node *& head, int value, node *& insert_after_me) {
node n; n.data = value;
node * new_node = &n;
if (insert_after_me == NULL) {
insert_after_me = new_node;
cout << "after assign insert: " << insert_after_me->data << endl;
head = new_node;
cout << "after assign head: " << head->data << endl;
}
}
int main () {
node * head = NULL;
node * new_node = NULL;
insert(head, 1, new_node);
cout << head->data << endl;
cout << new_node->data << endl;
cout << head << endl;
cout << new_node << endl;
}
This is obviously an imcomplete implementation, but when I run it I get the following as output:
after assign insert: 1
after assign head: 1
1
1924530936
0x7fff56177928
0x7fff56177928
This tells me in main, head and new_node are pointing to the same thing, yet they have different values stored in data. Why?
Note: Though it seems to me a nonsensical implementation to make insert take a node to insert after and then change that node, that's a requirement of the project. I can't change how insert is called.
I am having two issues with my c++ code (The test file is below):
I can't seem to figure out why its not breaking out of the while loop, when running, its stuck on the loop "7 versus 325".
So it should go into the next node of temp, which would be null, and then jump into the section where it adds it to the end of the queue. But its just looping and looping.
My second issue is with the the function I have commented out, queue1.back, whenever that is ran, it just errors out and gives what appears to be the address, but the .front() function works just fine.
The Test File I am working with is like this:
89 Alex
325 Rob
72 Joy
91 Bob
using namespace std;
class Person
{
friend class Pqueue;
public:
int priority;
string name;
};
class PQueue
{
friend class Person;
private:
//Structure for my linked list.
typedef struct node {
Person data;
struct node *next;
}Node, *NodePtr;
Node *head, *tail;
public:
//Prototype Functions
PQueue(void); //Initializer function
bool empty(void); //Test if empty
int size(void); //Return size
void enqueue(Person *); //Insert Node
void dequeue(void); //Remove Node
Person* front(void); //Access Next Node
Person* back(void); //Access last node
};
PQueue::PQueue()
{
head = NULL;
tail = NULL;
}
bool PQueue::empty(){
return (head == NULL);
}
void PQueue::enqueue(Person *myPerson){
NodePtr np = (NodePtr) malloc(sizeof(Node));
np->data = *myPerson;
np->next = NULL;
if(empty())
{
cout << "Making into creating the first node, of the linked list" <<endl;
head = np;
tail = np;
}
else { //Queue has more the one node
Node* temp = head;
if(np->data.priority > temp->data.priority) //If the priority is greater then the rest.
{
head = temp; //Saving my head pointer
head->data = np->data; //Assigning new Data to the head pointer
head->next = temp; //Assigning the rest of the linked list back into head.
cout << "Making into creating the first node again, having to reassign." <<endl;
}
else{
//Searching where to place the node.
while(temp->data.priority > np->data.priority) //Searching if the next priority is higher then the passed.
{
cout << "Inside the while loop: " << np->data.priority << " versus "<<temp->data.priority <<endl;
if(temp->next == NULL)
break;
temp = temp->next;
}
if(temp->next == NULL && np->data.priority < temp->data.priority) //Inserting at the end.
{
cout << "Making into creating the last node" <<endl;
tail->next = np;
cout << "Passing the function of creating the last node" <<endl;
}
else //Inserting into the middle of the function.
{
cout << "Inserting in the middle of the queue" <<endl;
np->next = temp->next;
temp->next = np;
}
}
}
}
void PQueue::dequeue(){
if(empty()){
cout << "\nAttempt to remove from an empty list." << endl;
exit(1);
}
Person hold = head->data;
NodePtr temp = head;
head=head->next;
if (head == NULL) tail = NULL;
free(temp);
}
Person* PQueue::front(){
//Person &temp = head->next->data;
//Person &temp = head->data;
Person &temp = head->data;
return &temp;
}
Person* PQueue::back(){
if(empty()){
cout << "\nNo entries in list." << endl;
exit(1);
}
Person &temp = tail->data;
return &temp;
}
int main() {
cout << "Starting main" << endl;
PQueue queue1; //Creating my queue.
cout << "Created Queue" << endl;
Person tempPerson;
ifstream inFile;
inFile.open("/tmp/temp");
cout << "going into while loop" << endl;
while (inFile >> tempPerson.priority >> tempPerson.name){
cout << "The priority is " << tempPerson.priority << " the name is " << tempPerson.name <<endl;
queue1.enqueue(&tempPerson);
}
//Testing Section, trying to get .front and .back to work.
Person *testPerson;
testPerson = queue1.front();
cout << "The TEST priority is " << testPerson->priority << " the TEST name is " << testPerson->name <<endl;
/**
Person *tailPerson;
testPerson = queue1.back();
cout << "The TEST priority is " << tailPerson->priority << " the TEST name is " << tailPerson->name <<endl;
**/
queue1.dequeue();
queue1.dequeue();
queue1.dequeue();
return 0;
}
When you add a new head entry to a non-empty list, you're mistakenly setting the next pointer to point right back at the node it's in, rather than setting it to point at the rest of the linked list like you intended.
head = temp; //Saving my head pointer
head->next = temp; //Assigning the rest of the linked list back into head.