为什么在使用单链表时在 tcache 2 中检测到 programm 抛出双重释放 [已关闭]

Why does programm throws double free detected in tcache 2 while using single linked list [closed]

提问人:Arsenyev01 提问时间:11/16/2022 最后编辑:Remy LebeauArsenyev01 更新时间:11/16/2022 访问量:53

问:


编辑问题以包括所需的行为、特定问题或错误以及重现问题所需的最短代码。这将有助于其他人回答这个问题。

去年关闭。

我试图创建函数以从单链表中删除所有值小于下一个(以下)元素值的元素。出于某种原因,programm 抛出“free():d ouble free detected in tcache 2”。我的功能有什么问题? list 不为空。


#include <iostream>
using namespace std;
struct Elem
{
    int num;
    Elem* next;
};

void deleteFromLinkedList(Elem* list) {
    Elem* curr, * next, *prev;
    curr = list;
    next = list->next;
 
    while (next != NULL)
    {
        if (curr->num < next->num) {
          
             prev->next=next;
             delete curr;
             curr = prev;
            continue;
           
        }
       prev = curr;
        curr = next;
        next = curr->next; 
    };
}
int main()
{
    Elem* first = NULL, * last = NULL, * p;
    int i;
    cout << "Enter any number or 0 to finish: ";
    cin >> i;
   
    while (i != 0)
    {
        p = new Elem;
        p->num = i;
        p->next = NULL;
        if (first == NULL)
        {
            first = last = p;
        }
        else
        {
            last->next = p;
            last = last->next;
        };
        cout << "Enter any number or 0 to finish: ";
        cin >> i;
    };
    deleteFromLinkedList(first);
C++ 内存 singlely-linked-list 分配

评论

0赞 Arsenyev01 11/16/2022
示例:删除前:15、12、11、7、9、5、2、3 删除后:15、12、11、9、5、3
0赞 UnholySheep 11/16/2022
请展示一个最小的可重现示例 - 您的错误很可能已经在其他地方开始了
0赞 drescherjm 11/16/2022
“可能”表示您尝试删除同一节点超过 1 次。
0赞 drescherjm 11/16/2022
void deleteFromLinkedList(Elem* list) {问题 #1 是按值而不是通过引用传递指向头节点的指针。这意味着即使正确实现了 deleteFromLinkedList(),您也永远无法更新指向 head 的指针。node
0赞 Thomas Matthews 11/16/2022
调试器。使用带有笔和纸的调试器。使用调试器遍历树时,使用笔和纸绘制节点和链接。

答:

1赞 Remy Lebeau 11/16/2022 #1

您的代码存在许多问题。

next = list->next;如果列表为空(即为 null),则为未定义的行为list

prev->next=next;是列表中第一个节点的未定义行为,因为未分配。prev

在它指向的节点之后,您不会更新,这也是未定义的行为currdelete

指针是按值传入的,因此如果列表中的第一个节点被释放,则调用方的指针无法更新,因此调用方将留下一个指向无效内存的悬空指针。list

请尝试以下操作:

void deleteFromLinkedList(Elem* &list) {

    if (!list)
        return;

    Elem *curr = list, *next = list->next, *prev = NULL;

    while (next)
    {
        if (curr->num < next->num) {
            if (prev)
                prev->next = next;
            else
                list = next;
            delete curr;
        }
        else {
            prev = curr;
        }
        curr = next;
        next = curr->next;
    }
}

在线演示


更新:在注释中,您更改了要求,要求在多次迭代中扫描列表。上面的代码适用于 1 次迭代,因此您可以简单地在一个循环中多次调用它,直到不再执行删除,例如:

bool deleteFromLinkedList(Elem* &list) {

    if (!list)
        return false;

    Elem *curr = list, *next = list->next, *prev = NULL;
    bool anyRemoved = false;

    while (next)
    {
        if (curr->num < next->num) {
            if (prev)
                prev->next = next;
            else
                list = next;
            delete curr;
            anyRemoved = true;
        }
        else {
            prev = curr;
        }
        curr = next;
        next = curr->next;
    }

    return anyRemoved;
}
...
while (deleteFromLinkedList(first));
...

在线演示

评论

0赞 Arsenyev01 11/16/2022
是的,但这只会删除一个元素。-1 我试图创建函数以从单链表中删除所有值较小的元素。所以 9,8,7,12,11,6 将是 12,11,6
0赞 user4581301 11/16/2022
@Arsenyev01 如果有一个删除一个节点的函数,则可以为每个需要删除的节点调用它。但要注意画家施莱米尔。
0赞 Remy Lebeau 11/16/2022
@Arsenyev01 您最初提供的示例应该产生,而我提供的代码完全正确地做到了这一点,我提供的演示证明了这一点。我刚才尝试了你的新示例,但输出不是.为什么会产生不小于?您似乎希望被删除,因为它们都小于 .在我发布我的答案后,您显然已经改变了您的要求。请不要那样做...15,12,11,7,9,5,2,315,12,11,9,5,39,8,7,12,11,69,8,12,11,612,11,69,8,7,12,11,612,11,6989,8,712
0赞 Remy Lebeau 11/16/2022
@Arsenyev01 如果您的需求发生了变化,请接受原来的问题,并针对新需求发布一个新问题(当然,在您尝试了基于您从该答案中学到的解决方案之后)。
1赞 Remy Lebeau 11/16/2022
@Arsenyev01你之前没有说过需要多次迭代。同样,你在事后不断改变需求,那么你怎么指望任何人给你一个准确的答案呢?为了将来参考,请在提出新问题时提前发布所有相关详细信息。无论如何,我已经给你的代码在 1 次迭代中工作正常,所以你可以简单地在循环中调用它,直到不再执行删除(工作演示)。我已经更新了我的答案以显示这一点。