Tableau de liste

kenikun Messages postés 8 Date d'inscription lundi 31 mars 2008 Statut Membre Dernière intervention 3 juillet 2008 - 18 mai 2008 à 16:31
cs_Edydy Messages postés 2 Date d'inscription mercredi 6 juillet 2005 Statut Membre Dernière intervention 13 septembre 2009 - 18 mai 2008 à 20:51
Bonjour,
J'ai un programme en C avec une liste chainee simple dont voici la declaration :
typedef struct Element_
{
    int map;
    char val[4];
    struct Element_ * suivant;
}Element;


Pour les besoins de mon application, je cree ensuite un tableau de liste.
Element * tab = (Element*)malloc(sizeof(Element)*76);

Le tableau est initialisé avec tous les map à  0, val à  "" et suivant à  NULL. Ensuite je remplis le tableau. Par exemple je peux avoir quelque chose du genre:

Case 0: val="abc\0" map=1 , suivant=NULL
.....
...
case 76: val="etc\0" map=5, suivant:val="epu\0" map=1, suivant=NULL

Mon programme fonctionne correctement et fait bien ce que je veux. Mais je rencontre un probleme lorsque je vais liberer l'espace alloué pour le tableau de liste. J'ai pensé à  faire une fonction qui permet de liberer une case et ensuite faire une boucle pour liberer toutes les autres.

int liberer(Element* p)
{
    Element *tmp;
    while(p)
    {
    tmp=p->suivant;
    free(p);
    p=tmp;
    }
    return 0;
}
Vu que je veux faire une modification, je passe en parametre un pointeur sur la case et j'appelle la fonction avec l'adresse de la case. Par exemple : liberer(&tab[0]);
Jusque là  tout va bien (enfin pour la premiere case), mais dès que je veux passer à  la case suivante, j'ai un SIGSEGV. J'ai regardé dans le debogueur et j'ai cette information : ***glibc detected *** /home/seb/appli/debug/src/appli: free(): invalid pointer: 0x0805e5e4 (c'est l'adresse de la case 1 apres avoir liberé la case 0).

Quelqu'un aurait-il une solution à  mon problème?
Merci

3 réponses

chaipo Messages postés 5 Date d'inscription samedi 12 janvier 2008 Statut Membre Dernière intervention 18 mai 2008
18 mai 2008 à 18:23
Salut,

euh si c'est juste libérer la place allouer à ce moment là: "Element * tab = (Element*)malloc(sizeof(Element)*76);" avec malloc, il suffit d'utiliser free.
0
cs_jfrancois Messages postés 482 Date d'inscription vendredi 26 août 2005 Statut Membre Dernière intervention 5 décembre 2009 2
18 mai 2008 à 19:52
Bonjour,

1) "Pour les besoins de mon application, je cree ensuite un tableau de liste."
Non, c'est juste un tableau de structures et non une liste ou un tableau de listes. Le champ suivant n'a aucune utilité du coup, d'ailleurs il est systématiquement mis à NULL dans le switch d'initialisation. A moins d'imaginer que, par la suite, les éléments du tableau se pointent les uns les autres, comme après un tri !

2) "J'ai pensé à  faire une fonction qui permet de liberer une case et ensuite faire une boucle pour liberer toutes les autres."
Pourquoi ? Les éléments de la liste n'ont pas été alloués, il n'y a donc pas de raison de les désallouer ! Quand la liste est créée, chaque élément occupe déjà sa pleine propre place : 1 entier + 4 caractères + 1 pointeur. Celà ne serait pas le cas (et il faudrait effectivement une boucle de désallocation) si val était un pointeur sur une chaîne de caractères allouée au moment de son initialisation. Une simple libération du tableau suffit.

3) Case 0: val="abc\0" map=1 , suivant=NULL ne va pas du tout !
c'est plutôt : case 0 : strcpy(val,"abc"); map=1; suivant=NULL; break;

Jean-François
0
cs_Edydy Messages postés 2 Date d'inscription mercredi 6 juillet 2005 Statut Membre Dernière intervention 13 septembre 2009
18 mai 2008 à 20:51
En résumé ce que jfrancois veut te dire c'est que le tu ne peux pas désallouer une case de ton tableau parce que tu as allouer tes 76 éléments d'un coup.

En gros le principe du free c'est une désallocation par malloc :

Tu fais un malloc, tu devras faire un free;
deux malloc, deux free...

Ton code devrait donc être dans ce style la alors pour l'allocation de mémoire et faire une vrai chaine liée,
mais l'inconvénient, c'est que tu ne pourra plus acceder par indice à tes éléments.

Element * tab = NULL;
Element* tmp = NULL;
//premier élément alloué
tab = (Element*)malloc(sizeof(Element));
tmp = tab;
for(int i = 0; i < 74; i++){
   tmp->suivant = (Element*)malloc(sizeof(Element));
   if(!tmp)
      error;
   tmp = tmp->suivant;
}
//dernier élément
   tmp->suivant = (Element*)malloc(sizeof(Element));
   if(!tmp)
      error;
   tmp->suivant = NULL;
0
Rejoignez-nous