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

77 Views Asked by At

Im trying to create function to delete from single-linked list all elements with value smaller as next (following) element value. For some reason programm throws "free():double free detected in tcache 2". What is wrong with my function ? list is not empty.


#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);
1

There are 1 best solutions below

8
Remy Lebeau On

There are a number of problems with your code.

next = list->next; is undefined behavior if the list is empty (ie list is null).

prev->next=next; is undefined behavior for the 1st node in the list, as prev is unassigned.

You are not updating curr after delete'ing the node it points at, which is also undefined behavior.

The list pointer is being passed in by value, so the caller's pointer can't be updated if the 1st node in the list is freed, thue the caller will be left with a dangling pointer to invalid memory.

Try this instead:

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;
    }
}

Online Demo


UPDATE: In comments, you changed your requirements to need the list scanned in multiple iterations. The code above works fine for 1 iteration, so you could simply call it multiple times in a loop until there are no more removals performed, eg:

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));
...

Online Demo