free():在调用赋值运算符时在 tcache 2 中检测到双重释放

free(): double free detected in tcache 2 on calling assignment operator

我刚刚问了一个非常相似的问题,但我已经看完了那个问题的答案,我只是看不出这次我做错了什么。我正在研究一个使用链表实现 c++ list<int> 的大学项目。我正在研究赋值运算符,这是我目前所拥有的。

Linkedlist &Linkedlist::operator=(const Linkedlist &l) {
    clear();
    if(l.empty())
    {
        return *this;
    }
    Node *iterRight = l.head;
    head = new Node;
    Node *iterLeft = head;
    while(iterRight != NULL)
    {
        iterLeft -> data = iterRight -> data;
        iterLeft -> next = new Node;
        iterLeft -> next -> prev = iterLeft;
        iterLeft = iterLeft -> next;
        iterRight = iterRight -> next;
    }
    return *this;
}

当我 运行 时,赋值运算符确实可以将数据从一个列表复制到另一个列表,但我在 运行 -

之后得到了这个
free(): double free detected in tcache 2

我不明白我是如何不恰当地使用我的指针的。有人可以告诉我我做错了什么吗?

编辑:析构函数也可能有用。

```
Linkedlist::~Linkedlist() {
Node *del;
while(head != NULL)
{
    del = head;
    head = head -> next;
    delete del;
}
}

编辑:抱歉,我是 Stack Overflow 的新手。如果我对 MRE 的理解正确,这里是要重现的最少代码量(上面的所有内容加上我的主程序和构造函数)。

int main() {
Linkedlist a(20);
Linkedlist b = a;
return 0;
}
Linkedlist::Linkedlist(unsigned int n) {
    size = n;
    tail = NULL;
    head = new Node;
    Node *iter = head;
    for(int i = 0; i < n; i++)
    {
        iter -> data = i;
        iter -> next = new Node;
        iter -> next -> prev = iter;
        iter = iter -> next;
    }
    tail = iter -> prev;
    tail -> next = NULL;
}

调用链表 a 的构造函数不会崩溃,它只会在我调用赋值后崩溃。我 运行 我在 valgrind 中的程序,但由于我在内存管理方面相当陌生,所以我不太确定我在看什么。它在我的析构函数中显示了我和无效的 free(),但我找不到它之前已经释放的位置。

行:

Linkedlist b = a;

调用复制构造函数,而不是赋值运算符。如果您没有提供复制构造函数,那么编译器生成的构造函数将只复制 head 指针。然后,在销毁期间,相同的 head 将从列表 a 和列表 b 中删除,导致“双重释放”。