队列:取消队列功能使程序崩溃

Queue: Dequeue function crashes program

本文关键字:队列 程序 崩溃 功能 取消      更新时间:2023-10-16

我正试图使用双链表在c++中创建一个队列。自从我被困在你排队的台阶上后,我还没有完全测试过所有的东西。根据MS Visual Studio 2013的说法,我试图创建一个临时节点,并四处移动,所以当我在队列中的头节点(称为队列)上调用delete,然后将头设置为下一个元素的临时节点时(你可以在代码中看到),但当我调用delete时,它就会崩溃。此外,为了增加这是多么奇怪,在调用堆栈之后,在调用delete之后,调用setPrev并设置prev节点,然后在那里崩溃。现在,我在任何析构函数删除过程中都不会调用这个函数,所以任何帮助都可以。我会尽力理解任何答案,但我对c++术语还是个新手。下面是我的代码。哦,最后一件事,总的来说,我所做的就是打一次入队,然后出队,然后删除

Node Class

#ifndef TSDNODE_H
#define TSDNODE_H
template <class T>
class DNode
{
    private:
        DNode<T>* next;
        DNode<T>* prev;
        T data;
    public:
        DNode(T);
        void setNext(DNode<T>* next);
        void setPrev(DNode<T>* prev);
        DNode<T>* getNext() const;
        DNode<T>* getPrev() const;
        T getData() const;
        void setData(T data);
        ~DNode();
};
template <class T>
DNode<T>::DNode(T data)
{
    this->next = nullptr;
    this->data = data;
    this->prev = nullptr;
}
template <class T>
void DNode<T>::setNext(DNode<T>* next)
{
    this->next = next;
}
template <class T>
void DNode<T>::setPrev(DNode<T>* prev)
{
    this->prev = prev;
}
template <class T>
DNode<T>* DNode<T>::getNext() const
{
    return this->next;
}
template <class T>
DNode<T>* DNode<T>::getPrev() const
{
    return this->prev;
}
template <class T>
T DNode<T>::getData() const
{
    return this->data;
}
template <class T>
void DNode<T>::setData(T data)
{
    this->data = data;
}
template <class T>
DNode<T>::~DNode()
{
    delete this->next;
    delete this->prev;
    this->next = nullptr;
    this->prev = nullptr;
}
#endif  /* TSDNODE_H */

Queue Class

#ifndef TSQUEUE_H
#define TSQUEUE_H
#include "TSDNode.h"
#include <string>
template <class T>
class Queue
{
    private:
        DNode<T>* queue;
        DNode<T>* tail;
        int size;
    public:
        Queue();
        void enqueue(T data);
        T dequeue();
        ~Queue();
};
template <class T>
Queue<T>::Queue()
{
    this->queue = nullptr;
    this->tail = this->queue;
    size = 0;
}

template <class T>
void Queue<T>::enqueue(T data)
{
    if (this->tail != NULL)
    {
        this->tail->setNext(new DNode<T>(data));
        this->tail->getNext()->setPrev(this->tail);
        this->tail = this->tail->getNext();
    }
    else
    {
        this->queue = new DNode<T>(data);
        this->tail = this->queue;
    }
    size++;
}
template <class T>
T Queue<T>::dequeue()
{
    T data;
    if (this->queue == nullptr)
    {
        delete this->tail;
        delete this->queue;
        this->tail = nullptr;
        std::string ex = "Exception: Empty Queuen";
        throw ex;
    }
    else if (this->queue != nullptr)
    {
        data = this->queue->getData();
        DNode<T>* node = this->queue->getNext();
        this->queue->setNext(nullptr);
        this->queue->setPrev(nullptr);
        node->setPrev(nullptr);
        //--------------------------------------------------- crashes here 
        delete this->queue;
        this->queue = node;
    }
    size--;
    return data;
}
template <class T>
Queue<T>::~Queue()
{
    delete this->queue;
    this->queue = nullptr;
    this->tail = nullptr;
}


#endif  /* TSQUEUE_H */

DNode析构函数中,您不希望删除nextprev节点。你只想删除这个节点,而不是它链接到的所有内容。

删除这些线路

delete this->next;
delete this->prev;

编辑:实际上这不是你的问题,因为在删除节点之前,你要清除nextprev值。我仍然认为最好不要自动删除整个链,但只要你与处理节点删除的方式一致,它应该仍然有效。

实际问题是,当您将最后一个节点出列时,您仍然试图设置此行中下一个节点的next指针:

node->setPrev(nullptr);
//--------------------------------------------------- crashes here 

此时node是nullptr,因此尝试访问node->next会导致崩溃。一个简单的if测试就是你所需要的

if (node != nullptr)
    node->setPrev(nullptr);
//--------------------------------------------------- no longer crashes here 

编辑2:还要注意,在队列中的下一个节点是nullptr的情况下,还需要将尾部设置为nullptr