free():调用赋值运算符时在 tcache 2 中检测到双重释放
Posted
技术标签:
【中文标题】free():调用赋值运算符时在 tcache 2 中检测到双重释放【英文标题】:free(): double free detected in tcache 2 on calling assignment operator 【发布时间】:2021-12-19 16:42:55 【问题描述】:我刚刚问了一个非常相似的问题,但我已经回答了这个问题的答案,我只是看不出这次我做错了什么。我正在研究一个使用链表实现 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;
当我运行时,assingment 运算符确实可以将数据从一个列表复制到另一个列表,但我在运行后得到了这个 -
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;
调用 Linkedlist a 的构造函数不会崩溃,它只会在我调用赋值时崩溃。我在 valgrind 中运行我的程序,但由于我在内存管理方面相当陌生,所以我不太确定我在看什么。它在我的析构函数中显示了我和无效的 free(),但我找不到它之前已经释放的位置。
【问题讨论】:
请提供minimal reproducible example;代码可能在其他地方。如果您遇到困难,请通过 valgrind 运行您的程序或在打开地址清理程序的情况下构建(它们都会告诉您数据首先在哪里delete
'd)。
仅此代码不会产生双重释放。没有minimal reproducible example,您只能猜测要显示的代码,而我们只能猜测未显示的代码。我目前的猜测? Rule of three.
对不起@DrewDormann,我想我用一个最小的可重现示例编辑了它。
您在此处显示的代码does not compile,因此无法重现您描述的消息。我非常有信心您仍然没有向我们展示更多代码。您的主要功能确实暗示了我之前的猜测,即您违反了我们尚未显示的代码中的Rule of Three。
【参考方案1】:
行:
Linkedlist b = a;
调用复制构造函数,而不是赋值运算符。如果您没有提供复制构造函数,那么编译器生成的只会复制head
指针。然后,在销毁过程中,相同的head
将从列表a
和列表b
中删除,从而导致“双重释放”。
【讨论】:
以上是关于free():调用赋值运算符时在 tcache 2 中检测到双重释放的主要内容,如果未能解决你的问题,请参考以下文章