Arsenyev01
Arsenyev01

Reputation: 1

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

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

Upvotes: -2

Views: 146

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 597941

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

Upvotes: 1

Related Questions