Loris Simonetti
Loris Simonetti

Reputation: 217

free(): double free detected in tcache 2 when deleting a list

#include <stdlib.h>

struct Stanza
{
    struct Stanza *avanti, *sinistra, *destra;
};
static struct Stanza *Stanza = NULL;
static struct Stanza *stanza_inizio = NULL;
static struct Stanza *lista_stanze = (struct Stanza *)&stanza_inizio;

void insertinlist(struct Stanza *Stanza)
{
    lista_stanze = Stanza;
    if (stanza_inizio == NULL)
        stanza_inizio = lista_stanze;
    else
    {
        lista_stanze->avanti = stanza_inizio;
        stanza_inizio = Stanza;
    }
}
void createElement(void)
{
    Stanza = (struct Stanza *)malloc(sizeof(struct Stanza));
    if (Stanza == NULL)
    {
        exit(2);
    }
    Stanza->avanti = Stanza->sinistra = Stanza->destra = NULL;
    stanza_inizio = Stanza;
    insertinlist(Stanza);
}
void delete (void)
{
    struct Stanza *scorritore = stanza_inizio;
    struct Stanza *successivo;
    if (scorritore == NULL)
    {
        // nothing
    }
    else
    {
        while (scorritore != NULL)
        {
            successivo = scorritore->avanti;
            free(scorritore); // error: double free detected in tcache
            scorritore = successivo;
        }
        stanza_inizio = NULL;
    }
}

int main()
{
    createElement();
    delete ();
}

I'm getting the error "free(): double free detected in tcache 2" caused by delete() function, when calling free, but can't understand why. I tried to use this code in a new blank file with a different list and it works perfectly fine, but with thislist something unknown to me is wrong

What's wrong here?

Upvotes: 1

Views: 2075

Answers (1)

Clifford
Clifford

Reputation: 93476

At this line in delete():

successivo = scorritore -> avanti;

successivo and scorritore->avanti have the same value in the first iteration of teh whole =-loop, so on the second iteration, there is an attempt to delete an already free'd block: enter image description here

So the problem is in the construction of the list rather then the delete() function. The line:

stanza_inizio = Stanza;

in createElement() seems unlikely to be intended. It prevents the first-time initialisation block in insertinlist():

if (stanza_inizio == NULL)
    stanza_inizio = lista_stanze;
else{

from running.

Deleting:

stanza_inizio = Stanza;

from createElement() at least allows the code to run to completion. I would not care to say whether the code is actually semantically correct beyond that correction (but I kind of doubt it).

However this initialisation at least is suspect:

static struct Stanza *lista_stanze = (struct Stanza *) &stanza_inizio;

&stanza_inizio has type struct Stanza** but you assign it to a struct Stanza*. It is unconditionally assigned in insertinList() in any event so it really serves no purpose.

Upvotes: 2

Related Questions