free():在 tcache 2 中检测到双重释放,在链表中删除 c++ 中的节点以及析构函数在此代码中的工作方式

free(): double free detected in tcache 2, in linked List deletion of a node in c++ and how destructor is working in this code

class Node{
    public:
        int data;
        Node* next;
        
        Node(int d){
            data = d;
            next = NULL;
        }
        
        ~Node(){
            delete next;
        }
};
class List{
    public:
        Node* head;
        Node* tail;
        
        List(){
            head = NULL;
            tail = NULL;
        }
        
        ~List(){
            delete head;
        }
        
        void push_back(int data){
            Node* n = new Node(data);
            if(head == NULL){
                head = tail = n;
            }else{
                tail->next = n;
                tail = n;
            }
        }
        void print(){
            Node* temp = head;
            while(temp != NULL){
                cout<<temp->data<<" ";
                temp = temp->next;
            }
        }
        void deleteNode(int d){
            Node* curr = head;
            Node* prev = NULL;
            while(curr != NULL){
                if(curr->data == d){
                    if(prev == NULL){
                        head = head->next;
                        delete curr;
                        break;
                    }else{
                        prev->next = curr->next;
                        curr->next = NULL;
                        delete curr;
                        break;
                    }
                }
                prev = curr;
                curr = curr->next;
            }
        }
};
int main(){
    List l;
    l.push_back(1);
    l.push_back(2);
    l.push_back(3);
    l.push_back(4);
    l.push_back(5);
    l.deleteNode(1);
    l.print();
}

如果我从1->2->3->4->5中删除1

预期输出:2->3->4->5

输出:free():在 tcache 2 中检测到双重释放;

原因:节点Class中的析构函数。如果我删除它工作正常。

疑问 : 如果我在节点class中删除析构函数在节点class 那我怎样才能释放内存。还有谁能解释一下 析构函数在 Node 和 List 中是如何工作的 class.

有人可以帮我解决这个问题,或者可以提供替代解决方案。

谢谢!!!

~Node(){ delete next; } 使得很难从该列表中删除单个节点。它也会删除它之后的 所有 个节点。

我建议 Node 个人不要 delete 关注 Node

class Node {
public:
    int data;
    Node* next;

    Node(int d) : // colon starts the member initializer list
        data(d), next(nullptr)
    {
        // the body of the constructor can now be empty
    }

    // No user-defined destructor needed here
};

相反,delete List 的析构函数中的所有 Node

    ~List() {
        for(Node* next; head; head = next) {
            next = head->next;
            delete head; 
        }
    }

与手头的问题无关。这些只是建议:

您可以使 Node 的构造函数更通用一些,这样就可以在构造时提供下一个 Node

class Node {
public:
    int data;
    Node* next;

    // `nullptr` below is a default argument that will be used if the
    // user of this class does not provide a second argument
    Node(int d, Node* n = nullptr) :
        data(d), next(n)
    {}
};

这可以在名为 push_frontList 成员函数中使用:

    void push_front(int data) {
        head = new Node(data, head);
        if(!tail) tail = head;
    }

与此无关,您 可以 使 push_back 更清晰一点,甚至根本不改变当前的 Node:

    void push_back(int data) {
        Node* n = new Node(data);

        if(tail)  tail->next = n;
        else      head = n;

        tail = n;
    }

为了跟进我的评论:扔掉你的 NodeList class,并实际使用语言:

#include <forward_list>
#include <iostream>

int main(){
    std::forward_list< int > l { 1, 2, 3, 4, 5 };
    l.remove( 1 );
    for ( auto & node : l )
    {
        std::cout << node << " ";
    }
}