【问题标题】:I am getting a breakpoint and i do not know why我得到一个断点,我不知道为什么
【发布时间】:2017-06-23 04:10:16
【问题描述】:

我正在尝试通过在 C++ 中使用链表来实现优先级队列。但是,当我运行程序时,它会在“priorityQLinkedList::dequeue()”方法中触发一个断点。有人能告诉我为什么会这样,并给我一些解决方法的建议吗?

代码:

#include <iostream>
#include <cstring>
#include <iomanip>

using namespace std; 

struct DAT
{
    int id;
    char fullname[50];
    double savings; 
};

struct NODE
{
    DAT data; 
    NODE *N; 
    NODE *P;
    NODE(const int i, const char *f, const double s)
    {
        data.id = i;
        strcpy_s(data.fullname, f);
        data.savings = s;
        N = NULL; 
        P = NULL; 
    }
};

class priorityQLinkedList
{
private:
    NODE *front; 
    NODE *back;
public:
    priorityQLinkedList() { front = NULL; back = NULL; }
    ~priorityQLinkedList() { destroyList(); }
    void enqueue(NODE *);
    NODE* dequeue();
    void destroyList(); 
};

void priorityQLinkedList::enqueue(NODE *n)
{
    if (front == NULL) {
        front = n;
        back = n;
    }

    else {
        NODE *temp = front;
        if (n->data.id > temp->data.id)
        {
            front->P = n;
            n->N = front; 
            front = n; 
        }
        else
        {
            //search for the posistion for the new node. 
            while (n->data.id < temp->data.id)
            {
                if (temp->N == NULL) {
                    break; 
                }
                temp = temp->N; 
            }

            //New node id's smallest then all others
            if (temp->N == NULL && n->data.id < temp->data.id)
            {
                back->N = n;
                n->P = back;
                back = n; 
            }

            //New node id's is in the medium range.
            else {
                temp->P->N = n; 
                n->P = temp->P; 
                n->N = temp;
                temp->P = n; 
            }
        }
    }
}

NODE* priorityQLinkedList::dequeue()
{
    NODE *temp; 

    //no nodes
    if (back == NULL) {
        return NULL; 
    }

    //there is only one node
    else if (back->P == NULL) {
        NODE *temp2 = back; 
        temp = temp2;
        front = NULL;
        back = NULL; 
        delete temp2;
        return temp; 
    }

    //there are more than one node
    else {
        NODE *temp2 = back;
        temp = temp2; 
        back = back->P;
        back->N = NULL;
        delete temp2;
        return temp;
    }

}

void priorityQLinkedList::destroyList()
{
    while (front != NULL) {
        NODE *temp = front; 
        front = front->N;
        delete temp; 
    }
}

void disp(NODE *m) {
    if (m == NULL) {
        cout << "\nQueue is Empty!!!" << endl; 
    }
    else {
        cout << "\nID No.   : " << m->data.id; 
        cout << "\nFull Name    : " << m->data.fullname; 
        cout << "\nSalary   : " << setprecision(15) << m->data.savings << endl; 
    }
}

int main() {
    priorityQLinkedList *Queue = new priorityQLinkedList();

    NODE No1(101, "Qasim Imtiaz", 567000.0000);
    NODE No2(102, "Hamad Ahmed", 360200.0000);
    NODE No3(103, "Fahad Ahmed", 726000.0000); 
    NODE No4(104, "Usmaan Arif", 689000.0000); 

    Queue->enqueue(&No4); 
    Queue->enqueue(&No3);
    Queue->enqueue(&No1);
    Queue->enqueue(&No2); 

    disp(Queue->dequeue());
    disp(Queue->dequeue());
    disp(Queue->dequeue());
    disp(Queue->dequeue()); 
    disp(Queue->dequeue());

    delete Queue; 
    return 0; 
}

【问题讨论】:

  • 如果我弄错了,请纠正我,但是如果您 delete 将要出列的节点然后返回指向该节点的指针,这不会给调用者带来问题,然后调用者会得到返回一个“死”指针?
  • @TimBiegeleisen 这就是正在发生的事情,你应该把它写成答案
  • @AndersK。我在下面尝试了一个答案。我没有看到处理这个问题的好方法,但我当然认为dequeue() 应该删除目标节点。我的回答是复制NODE 并返回给调用者。但随后调用者必须在某个时候调用delete
  • 是的,这段代码的所有权很难看到。最好使用智能指针,然后函数可以返回一个共享指针。

标签: c++ linked-list breakpoints priority-queue


【解决方案1】:

在您的dequeue() 方法中突出的一个问题是您在NODE 指针上调用delete,然后尝试将此已删除的指针返回给调用者。这可能会导致 dequeue() 本身出现错误,或者肯定会导致认为自己正在获取指向实际活动 NODE 对象的指针的调用者出现错误。

一个可能的解决方法是创建一个正在出队的NODE 的副本。你仍然会从你的列表中删除目标,但是调用者会返回一个有效的指针,他可以在以后释放它。

NODE* priorityQLinkedList::dequeue()
{
    NODE *temp; 

    // no nodes
    if (back == NULL) {
        return NULL; 
    }

    NODE *temp2 = back; 
    temp = new NODE(temp2->data.id, temp2->data.fullname, temp2->data.savings);

    // there is only one node
    else if (back->P == NULL) {
        front = NULL;
        back = NULL; 
        delete temp2;
        return temp; 
    }

    // there are more than one node
    else {
        back = back->P;
        back->N = NULL;
        delete temp2;
        return temp;
    }
}

【讨论】:

  • 您假设 priorityQLinkedList 拥有节点指针。它不是。它们被传递给enqueue,并归enqueue 的调用者所有。此解决方案不会解决 OP 的问题。
  • @1201ProgramAlarm 请编辑我的答案并修复它。我不是 C++ 大师,但返回已删除的指针对我来说有异味。希望我对 C++ 有更多了解。
【解决方案2】:

您正在删除 dequeue 中不属于 priorityQLinkedList 的指针,因此您不知道删除它们是否安全。

在这种情况下,它们不是,因为传递给enqueue 的节点指针是本地的、基于堆栈的变量的地址,并且没有被new 分配。 (还有已经提到的删除指针然后返回它的问题,这是未定义的行为。)

对所示代码的修复是删除对dequeue 中的delete 的调用。但是,如果进行更改以便动态分配传递给 enqueue 的节点,则需要添加一些东西来处理。

【讨论】:

    【解决方案3】:

    1.首先将strcpy_s改为strcpy是struct NODE。

    2. 使用 temp2--代替 Delete(temp2)。

    //no nodes
    if (back == NULL) {
        return NULL;
    }
    
    //there is only one node
    else if (back->P == NULL) {
        NODE *temp2 = back;
        temp = temp2;
        front = NULL;
        back = NULL;
        temp2--;
        return temp;
    }
    
    //there are more than one node
    else {
        NODE *temp2 = back;
        temp = temp2;
        back = back->P;
        back->N = NULL;
        temp2--;
        return temp;
    }
    

    我希望这能解决问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多