C++ Linked List Queue pointers causing undefined behavior - c++

I've read the questions and not seen answer to mine.
Most people use structs for these and after testing reference code I see the struct version is functional but, why is class version not?
#include <iostream>
using namespace std;
// I'm still bad at pointer logic but it makes sense.
// REFERENCES
// https://www.geeksforgeeks.org/queue-linked-list-implementation/
// stack linked list assignment earlier in semester
// https://stackoverflow.com/questions/29787026/c-queue-from-linked-list
class Node {
public:
int data;
Node *next; // controls flow of nodes
};
class Queue {
public:
Queue();
~Queue();
void enQueue(int data);
void deQueue();
bool isEmpty();
//private: all set to public because I don't want to make a print function
Node *front;
Node *rear;
int counter;
};
Queue::Queue()
{
front = NULL;
rear = NULL;
}
Queue::~Queue() {
if (rear == NULL && front == NULL)
{
cout << "Nothing to clean up!" << endl;
}
else
{
cout << "Delete should be happening now...";
}
}
void Queue::enQueue(int data) {
// create new node of queue structure
Node *temp = new Node;
temp->data = data;
// write like this line below if not temp->data = data;
// Node *temp = new Node(data);
// if the queue is empty, first node.
if (rear == NULL)
{
front = temp;
rear = temp;
return;
}
// assign data of queue structure
rear->next = temp; // point rear pointer to next pointer = assign to temp
rear = temp; // assign rear to temp keep front pointer at beginning fifo
}
void Queue::deQueue()
{
// if queue is empty, return NULL
if (front == NULL)
{
cout << "Queue is empty, sorry!";
return;
}
Node* temp = front; // assign front
//problem here
front = front->next; // move front one node ahead
if(front == NULL)
{
rear = NULL;
}
delete (temp);
return;
}
bool Queue::isEmpty()
{
// cout << "functions";
// cout << endl;
return (front == NULL && rear == NULL);
}
int main()
{
Queue yay;
yay.isEmpty();
yay.deQueue();
cout << endl;
yay.enQueue(5);
yay.enQueue(6);
cout << "Queue Front : " << (yay.front)->data << endl;
yay.deQueue();
cout << "After deqQueue " << endl;
cout << "Queue Front : " << (yay.front)->data << endl;
yay.deQueue();
cout << "Queue Front : " << (yay.front)->data << endl;
yay.deQueue(); // <- Problem here
yay.deQueue();
cout << "completed" << endl;
}
I've isolated the problem to line 90
//problem here
front = front->next; // move front one node ahead
it causes this code in int main() to not print
yay.deQueue(); // <- Problem here
yay.deQueue();
cout << "completed" << endl;
I know I am weak at pointer directing and so forth, so if could please tell me what I am not seeing would be appreciated, I've been poking at it for a while now and did not resolve.
This link for code through online gdb
https://onlinegdb.com/0B0KzcHMa
This is the output with line
Queue is empty, sorry!
Queue Front : 5
After deQueue
Queue Front : 6
And the output with line 90 and 96 commented out //96 commented to avoid double free
Queue is empty, sorry!
Queue Front : 5
After deQueue
Queue Front : 5
Queue Front : 5
completed
Delete should be happening now...
Now I know, I know I should be better at this traversal of nodes business
but, I am not seeing it and this may help me remember it in the future :X
I believe its a simple fix but, everything I try reaches the former output
rather than the later with intended data represented, I believe it is
nexting out into random memory making memory leak or memory pointing wherever
thus it never goes back to main to complete terminal messages

The problem is here:
Queue yay;
yay.isEmpty();
yay.deQueue();
cout << endl;
yay.enQueue(5);
yay.enQueue(6);
cout << "Queue Front : " << (yay.front)->data << endl;
yay.deQueue();
cout << "After deqQueue " << endl;
cout << "Queue Front : " << (yay.front)->data << endl;
yay.deQueue();
cout << "Queue Front : " << (yay.front)->data << endl; // <<==== HERE
The queue had two elements, 5 and 6, inserted. Then one was popped, then the other. That means yay.front is now nullptr per your deQueue logic reading the end of the list. Therefore, reading (yay.front)->data invoke undefined behavior by dereferencing an invalid pointer (in this case a pointer containing nullptr).
Lose that dereference (one way or another) and the code shouldn't fault any longer.

Related

Segmentation errors(core dumped) after deleting pointers

I am trying to make a mask delivery, ordering service code.
The function order will add a new order to order list.
The function output will output the list from newest to oldest order.
The function deliver removes the oldest order.
The following is the code:
#include <iostream>
#include <string>
using namespace std;
struct Mask {
string type;
string customer;
Mask *next;
};
void order(Mask *&head, string type, string customer){
cout << "Ordering " << type << " for " << customer << endl;
Mask *oldHead = head;
head = new Mask;
head->type = type;
head->customer = customer;
head->next = oldHead;
}
void output(Mask *head){
cout << "Outputting order list " << endl;
for (Mask *p = head; p != NULL; p = p->next)
cout << " " << p->type << " for " << p->customer << endl;
}
void deliver(Mask *&head){
if (head->next == NULL){
cout << "Delivering " << head->type;
cout << " for " << head->customer << endl;
delete head;
}
else
deliver(head->next);
}
int main()
{
Mask *head = NULL;
order(head, "3M-N95", "Alice");
order(head, "OxyAir", "Burce");
order(head, "3M-N95", "Cindy");
output(head);
deliver(head);
output(head);
}
Everything runs smoothly, but it says segmentation error(core dumped) at the end. I tried adding this:
if (head->next->next == NULL){
deliver(head->next);
head->next == NULL;
}
But the problem still exists. Any help is appreciated.
I changed deliver to this:
void deliver(Mask *&head){
if (head->next->next == NULL){
cout << "Delivering " << head->next->type;
cout << " for " << head->next->customer << endl;
head->next = head->next->next;
delete head->next;
}
else
deliver(head->next);
}
Apparently, just setting the pointer to NULL does not fix the problem, so I just updated it so that the second last pointer pointed directly to the end.
in "deliver" you force the function to meet the condition if(head->next == NULL)
and then trying to reach head->next->next which is like trying to say null->next (resulting with segmentation fault).
I would recommend traversing to the last "Mask" object with a while loop instead of using all those "if" statements which lead to the same result, or at least change the second if to else if in order to avoid meeting this "if" again.

Displaying null children of binary tree in output

I have a method that prints the levels of a binary tree:
template<class BTNode>
void breadthfirstByLevel(BTNode* node_ptr) {
if (node_ptr == NULL)
{
return;
}
queue<BTNode *> q1;
queue<BTNode *> q2;
q1.push(node_ptr);
while (!q1.empty() || !q2.empty()) {
while (!q1.empty())
{
node_ptr = q1.front();
q1.pop();
cout << node_ptr->data() << " ";
if (node_ptr->left() != NULL)
{
q2.push(node_ptr->left());
}
if (node_ptr->right() != NULL)
{
q2.push(node_ptr->right());
}
}
cout << endl;
while (!q2.empty())
{
node_ptr = q2.front();
q2.pop();
cout << node_ptr->data() << " ";
if (node_ptr->left() != NULL)
{
q1.push(node_ptr->left());
}
if (node_ptr->right() != NULL)
{
q1.push(node_ptr->right());
}
}
cout << endl;
}
}
I check for the children of the current node to be null and push them into the queue. How can I display "NULL" in the level output instead of just skipping it and printing nothing?
You take the pointer of the next node from the queue to print data. If this node has children (i.e. pointer to child not null), you put them in the queue. This means that in the queue you'll never have a nullptr.
You can solve this using a variant of the algorithm: you could put nullptr in the queue in absence of child. But you then have to make sure when you get pointers from the queue not to dereference them.
...
while (!q1.empty() || !q2.empty()) {
while (!q1.empty())
{
node_ptr = q1.front();
q1.pop();
if (node_ptr==nullptr) { // if nullptr was on queue
cout << "<NULL> "; // tell it
}
else { // otherwise handle data and queue its children
cout << node_ptr->data() << " ";
q2.push(node_ptr->left()); // push even if it's nullptr
q2.push(node_ptr->right()); // " "
}
}
... // then same for q2
}

Cout giving a weird output

This is for a lab I have done, which is to create a simple queue using C++.
#include "Task5.h"
#include <iostream>
using namespace std;
void push(const long &i, node* &n) {
if (n == NULL) {
node *ptr = new node;
ptr -> item = i;
ptr -> next = NULL;
n = ptr;
cout << "Created New Node." << endl;
}
else {
node *ptr = n;
cout << "Created Pointer" << endl;
while (ptr -> next != NULL){
cout << "Finding Next..." << endl;
ptr = ptr -> next;
}
cout << "I'm here." << endl;
node *temp = new node;
temp -> item = i;
ptr -> next = temp;
cout << "Node Created." << endl;
}
}
long pop(node* &n) {
if (n == NULL) cout << "HEY!!! Can't pop an empty queue." << endl;
else {
long val;
node *ptr = n;
n = n -> next;
val = ptr -> item;
delete ptr;
return val;
}
}
int main() {
node *head = NULL;
push(13,head);
push(10,head);
push(18,head);
push(22,head);
cout << pop(head) << endl;
cout << pop(head) << endl;
cout << pop(head) << endl;
cout << pop(head) << endl;
cout << pop(head) << endl;
cout << pop(head) << endl;
}
This is giving the following output:
Created New Node.
Created Pointer
I'm Here.
Node Created.
Created Pointer
Finding Next...
I'm here.
Node Created.
Created Pointer
Finding Next...
Finding Next...
I'm here.
Node Created.
13
10
18
22
HEY!!! Can't pop an empty queue.
6296192
HEY!!! Can't pop an empty queue.
6296192
So the end result is that the code works, HOWEVER it outputs 6296192 randomly. I thought maybe I misspell something or cout is converting endl; to hex. My lab instructor also has no idea what's happening. Can someone tell me what is happening? If it helps, I am running this code via Linux-run terminal.
Thanks in advance.
In your function:
long pop(node* &n) {
you don't return anything in case of n == NULL is true. So this is UB, and might also cause such random values in output.
I'd suggest using the debugger with a breakpoint on the first cout << pop(head) << endl; and watch the value returned from pop each time.
Also the compiler is probably giving you a warning about the cause of the issue, always pay attention to the warnings it usually means something unintended will happen.
The cout << pop(head) << endl; uses the value returned by pop() but in the case of an empty queue there is no value returned, resulting in undefined behavior.

Pointers and static and new objects

First of all, apologies if this is a duplicate question. I'm just learning C++ and probably don't know the correct search terms to find what I'm sure has already been asked.
Anyways, I'm teaching myself C++ by working through the 30 days of code on HackerRank. However, I've hit a roadblock that I can't seem to solve when asked to implement an insert method for a LinkedList. Conceptually, I know what needs to be done, but syntactically I'm running into an issue.
Below is my code, with debugging printouts included. What seems to be happening is that new_node keeps getting put in the same location in memory, regardless of which loop iteration its on. How do I ensure this gets a new place in memory? I seem to get the same behavior regardless of if I declare new_node as static or not.
Here's the code:
#include <iostream>
#include <cstddef>
using namespace std;
class Node
{
public:
int data;
Node *next;
Node(int d){
data=d;
next=NULL;
}
};
class Solution{
public:
/// ----- MY CODE BEGINS HERE:
Node* insert(Node *head,int data)
{
cout << "----------" << endl;
cout << data << endl;
int i = 0;
if (head){
Node *curr = head;
Node *next = curr->next;
while(next){
cout << data << "," << i << ": " << curr << "," << curr->next
<< "," << curr->data << endl;
i++;
curr = curr->next;
next = curr->next;
}
cout << data << "," << i << ": " << curr << "," << curr->next
<< "," << curr->data << endl;
static Node new_node = Node(data);
curr->next = &new_node;
cout << " *** Adding " << data << " at " << curr->next
<< " and next points to: " << (curr->next)->next << endl;
return head;
}
else{
static Node new_head = Node(data);
cout << " *** Adding " << data << " at " << &new_head
<< " and next points to: " << new_head.next << endl;
return &new_head;
}
}
// ------- MY CODE ENDS HERE
void display(Node *head)
{
Node *start=head;
while(start)
{
cout<<start->data<<" ";
start=start->next;
}
}
};
int main()
{
Node* head=NULL;
Solution mylist;
int T,data;
cin>>T;
while(T-->0){
cin>>data;
head=mylist.insert(head,data);
}
mylist.display(head);
}
When I run this with the sample input of (4, 2, 3, 4, 1), I get the following:
----------
2
*** Adding 2 at 0x6022e0 and next points to: 0
----------
3
3,0: 0x6022e0,0,2
*** Adding 3 at 0x7fff3ddc1d80 and next points to: 0
----------
4
4,0: 0x6022e0,0x7fff3ddc1d80,2
4,1: 0x7fff3ddc1d80,0,3
*** Adding 4 at 0x7fff3ddc1d80 and next points to: 0x7fff3ddc1d80
----------
1
1,0: 0x6022e0,0x7fff3ddc1d80,2
1,1: 0x7fff3ddc1d80,0x7fff3ddc1d80,4
1,2: 0x7fff3ddc1d80,0x7fff3ddc1d80,4
1,3: 0x7fff3ddc1d80,0x7fff3ddc1d80,4
1,4: 0x7fff3ddc1d80,0x7fff3ddc1d80,4
1,5: 0x7fff3ddc1d80,0x7fff3ddc1d80,4
and this continues until a Segmentation Fault ebcause its caught in an infinite loop...
Any ideas why new_node keeps getting placed in the same memory location (with or without the static)? Is this not even the main issue and I'm completely missing the point? Thanks in advance!
-- C++ neophyte.
EDIT: The suggested duplicate doesn't quite address the question here. My trouble was not understanding the difference between pointers and references, but rather the difference between:
Node node_1 = Node(data);
static node_2 = Node(data);
node_3 = new Node(data);
As I was unaware of the new operator at the time of writing the question (obviously!), I did not know to (a) search for this or (b) include this term in the title. The title has been edited for clarity, and this edit has been included for future readers.
When you declare a variable static, there's only one copy of that variable. It gets created the first time you execute the declaration, and future calls to the function reuse the same data. So every time you use new_node, it's the same node.
You need to allocate dynamic data with the new operator. As the operator name implies, this creates a new object every time you use it. When you add a remove() operation to the class, it will use delete to free the memory.
Node* insert(Node *head,int data)
{
cout << "----------" << endl;
cout << data << endl;
int i = 0;
if (head){
Node *curr = head;
Node *next = curr->next;
while(next){
cout << data << "," << i << ": " << curr << "," << curr->next
<< "," << curr->data << endl;
i++;
curr = curr->next;
next = curr->next;
}
cout << data << "," << i << ": " << curr << "," << curr->next
<< "," << curr->data << endl;
Node *new_node = new Node(data);
curr->next = new_node;
cout << " *** Adding " << data << " at " << curr->next
<< " and next points to: " << (curr->next)->next << endl;
return head;
}
else{
Node *new_head = new Node(data);
cout << " *** Adding " << data << " at " << &new_head
<< " and next points to: " << new_head->next << endl;
return new_head;
}
}
you use a static variables. These are created only once, and are the same for every function call!
your intend is to create a new Node always, so these variables are not static!
try it out with
Node* new_head = new Node(data);
return new_head;
// as well as
Node* new_node = new Node(data);
curr->next = new_node;
All nodes must be create on the free store (with new), otherwise they get cleaned up when the function ends.
This means you are always referencing to not existing variables, which is a memory corruption. You must as well provide a destructor to delete the new'd nodes.
For more information read about the lifespan of variables.
Further notes:
use nullptr
std::list, or std::linked_list are the containers for lists (i know, you want to learn, but take a look at them)
your class is all public -> you can use a struct, since its the same, but default public for access specifiers.
use unique_ptr for the ownership (this is kinda advanced, but use it early)

C++ Priority Queue Class with Linked List

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.