'C++ Linked List Queue pointers causing undefined behavior
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
Solution 1:[1]
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.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | WhozCraig |
