2010-12-15 182 views
1

Je cours dans un double gratuit, et je ne peux pas voir où cela se passe. L'objectif du code suivant est de supprimer des nœuds Person d'une liste liée.C Double Gratuit Problème

typedef struct person { 
    char *first ; 
    char *last ; 
    char *location ; 
    struct person *next_person ; 
} person ; 

struct person_list { 
    int num_persons ; 
    person *first_person ; 
} person_list ; 

extern struct person_list person_list ; 

void free_person(person *person) { 
    free(person->first); 
    person->first = NULL; 

    free(person->last); 
    person->last = NULL; 

    free(person->location); 
    person->location = NULL; 

    free(person); 
    person = NULL; 
} 

... 

    if (person_list.num_persons > 0) { 
     while (person_list.num_persons > 0) { 
      //Iterate to the end of the chain. 
      cur_person = person_list.first_person; 

      while (cur_person->next_person != NULL) { 
       cur_person = cur_person->next_person; 
      } 

      free_person(cur_person); 
      person_list.num_persons--; 
     } 
    } 

... 

Répondre

5

Lorsque vous libérez la personne, vous ne définissez pas le pointeur next_person de la personne précédente à NULL. Par conséquent, il pointe vers la mémoire libérée, et c'est pourquoi vous êtes en double libération.

Vous devez garder une trace de la personne arrivant juste avant celle que vous souhaitez libérer et définir son pointeur next_person sur NULL.

Une autre façon plus efficace d'écrire votre boucle serait la suivante, qui ne sont pas soumis à la même erreur:

// Grab the first person 
    cur_person = person_list.first_person; 

    // Make sure there is someone to free 
    while (cur_person != NULL) { 
     // Keep track of who to free next 
     nxt_person = cur_person->next_person; 

     free_person(cur_person); 

     // Get the next person in line 
     cur_person = nxt_person; 
    } 

    // Didn't we just remove them all? Yes, we did. 
    person_list.num_persons = 0; 
    // Let's not forget to set that we have no one left 
    person_list.first_person = NULL; 
+0

Mais free_person définit cette personne sur NULL. Pourquoi ça ne marche pas? – Mike

+2

Comme l'écrit pmg, il ne définit que la copie locale dans la fonction. Vous devrez le définir sur NULL en dehors de la fonction, ou passer une référence (qui est une fonctionnalité C++, pas C). – Wolf

+0

Cela a du sens. Je vous remercie! – Mike

1
void free_person(person *person) { 
    /* ... */ 
    free(person); 
    person = NULL; 
} 

Ceci définit seulement le person local NULL; il n'y a aucun changement à la personne sur la routine d'appel.

1

Dans la fonction free_person, les affectations à NULL ne sont pas vraiment nécessaires car vous libérez également la structure conteneur. Sinon, il serait nécessaire d'éviter d'avoir un dangling pointer.

En outre, person = NULL affecte uniquement le paramètre local de la fonction qui est perdue juste après son retour.