web-dev-qa-db-fra.com

LinkedList - Comment libérer la mémoire allouée en utilisant malloc

J'ai un code C très simple pour construire une liste à liaison unique comme ci-dessous, dans lequel j'alloue dynamiquement de la mémoire pour chaque nœud en utilisant malloc. À la fin du code, je veux libérer la mémoire pour chaque nœud alloué, je me demandais comment procéder - Si je commence par le nœud principal et le libère, les pointeurs vers les nœuds suivants sont perdus et une fuite de mémoire se produit.

Une autre façon est de démarrer à partir du nœud principal et de conserver le pointeur de nœud dans un tableau séparé de pointeurs ou quelque chose, parcourez la liste jusqu'au pointeur de queue tout en stockant les pointeurs de nœud, et une fois atteint le nœud de queue, stockez-le également dans l'autre tableau de pointeurs et commencez à libérer cet index de tableau vers l'arrière jusqu'à ce que le nœud principal soit libéré.

Est-ce la seule façon de réaliser ce que j'essaie de faire?

Si je ne veux pas utiliser le deuxième tampon, comment dois-je procéder?.

#include "stdio.h"
#include "stdlib.h"

struct lnk_lst 
{
   int val;
   struct lnk_lst * next;
};

typedef struct lnk_lst item;


main()
{
   item * curr, * head;
   int i,desired_value;

   head = NULL;

   for(i=1;i<=10;i++) 
   {
      curr = (item *)malloc(sizeof(item));
      curr->val = i;
      curr->next  = head;
      head = curr;
   }

   curr = head;


   while(curr) {
      printf("%d\n", curr->val);
      curr = curr->next;
   }

  //How to free the memory for the nodes in this list?
   for(i=1;i<=10;i++)
   {
       free()//?? What logic here
   }


}
32
goldenmean

La manière habituelle est avec (pseudo-code en premier):

node = head              # start at the head.
while node != null:      # traverse entire list.
    temp = node          # save node pointer.
    node = node.next     # advance to next.
    free temp            # free the saved one.
head = null              # finally, mark as empty list.

L'idée de base est de se souvenir du nœud à libérer dans une variable distincte puis de passer au suivant avant de le libérer.

Vous avez seulement besoin de vous rappeler n nœud à la fois, pas la liste entière que vous proposez.

En termes de ce que vous devez ajouter à votre code, vous pouvez, lors de la suppression, utiliser head comme tête de liste de mise à jour continue (comme il est censé être) et curr pour stocker l'élément que vous supprimons actuellement:

while ((curr = head) != NULL) { // set curr to head, stop if list empty.
    head = head->next;          // advance head to next element.
    free (curr);                // delete saved pointer.
}

C'est un peu plus court que le pseudo-code ci-dessus simplement parce qu'il profite du raccourci C pour certaines opérations.

65
paxdiablo

J'utilise quelque chose comme ça:

for (p = curr; NULL != p; p = next) {
    next = p->next;
    free(p);
}
9
cnicutar

Votre code gratuit doit être le suivant:

lnk_lst temp = null;
while(head) 
{
  temp = head->next;
  free(head);
  head = temp;
}

Je voudrais également ajouter après votre malloc que vous voulez probablement vérifier si le mem a été alloué avec succès .. quelque chose comme

if(curr)
2
Baz1nga

Vous parcourez la liste en utilisant la même logique que ci-dessus. Vous enregistrez le curseur -> pointeur suivant quelque part, libérez la structure du curseur et affectez le curseur avec le curseur enregistré -> pointeur suivant

1
duedl0r