IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Liste chainée corrompue


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 27
    Par défaut Liste chainée corrompue
    Bonjour,

    J'ai un petit problème avec ma fonction ajouter concernant ma liste chaînée.
    Je suis certains à 100% que c'est cette fonction qui pose problème.

    La suite de mon code marche très bien.
    J'ai tenté de voir ce qui en ressort avec Sysalloc mais rien à signaler.

    J'ai par contre créer une fonction détruire() qui libère l'espace mémoire de ma liste et là j'obtiens une erreur. (c'est un simple free de toute la liste )

    J'en déduis donc que ma liste est probablement corrompue!
    Voilà le code.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
     
     
    typedef int coord [8];
     
    typedef struct cell cell;
    struct cell{
       int  coordonees [8];
       cell *suiv;
    };
     
    /* Fonction qui pose problème */
    cell *ajouter(cell *pc, int *table) 
    { 
      int i=0;
      if (pc == NULL)
      {
        cell *der = malloc(2*sizeof(cell));
        for(i=0; i<8; i++)  
    	    der->coordonees[i] = table[i]; //Je soupçonne cette ligne d'en être à l'origine
    	der->suiv = NULL;
        return der;
     
      }
      pc->suiv = ajouter(pc->suiv, table);	       
      return pc;
    }
     
    int main ()
    {
        coord init;
     
        cell *pc = NULL; 
         pc=ajouter(pc, init); 
         afficher(pc);  
          //      sys_mem_trace();
         detruire(pc); // Produit un message d'erreur 
     return 0;
    }
    Le message d'erreur proprement dit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    
    5 11 9 8 18 13 8 4  // Résultat de la fonction afficher()  
    
    *** glibc detected *** test: free(): invalid next size (fast): 0x00000000006061d0 ***
    ======= Backtrace: =========
    /lib/libc.so.6(+0x71e16)[0x7ffff786ce16]
    /lib/libc.so.6(cfree+0x6c)[0x7ffff7871b8c]
    /test[0x401774]
    /test[0x401794]
    /test[0x40202d]
    /lib/libc.so.6(__libc_start_main+0xfd)[0x7ffff7819c8d]
    /test[0x400b69]
    ======= Memory map: ========
    00400000-00406000 r-xp 00000000 08:09 2229919                         
    00605000-00606000 rw-p 00005000 08:09 2229919                            
    00606000-00627000 rw-p 00000000 00:00 0                                  [heap]
    7ffff0000000-7ffff0021000 rw-p 00000000 00:00 0 
    7ffff0021000-7ffff4000000 ---p 00000000 00:00 0 
    7ffff75e5000-7ffff75fb000 r-xp 00000000 08:03 1305603                    /lib/libgcc_s.so.1
    7ffff75fb000-7ffff77fa000 ---p 00016000 08:03 1305603                    /lib/libgcc_s.so.1
    7ffff77fa000-7ffff77fb000 rw-p 00015000 08:03 1305603                    /lib/libgcc_s.so.1
    7ffff77fb000-7ffff7954000 r-xp 00000000 08:03 1309157                    /lib/libc-2.11.3.so
    7ffff7954000-7ffff7b53000 ---p 00159000 08:03 1309157                    /lib/libc-2.11.3.so
    7ffff7b53000-7ffff7b57000 r--p 00158000 08:03 1309157                    /lib/libc-2.11.3.so
    7ffff7b57000-7ffff7b58000 rw-p 0015c000 08:03 1309157                    /lib/libc-2.11.3.so
    7ffff7b58000-7ffff7b5d000 rw-p 00000000 00:00 0 
    7ffff7b5d000-7ffff7bdd000 r-xp 00000000 08:03 1309170                    /lib/libm-2.11.3.so
    7ffff7bdd000-7ffff7ddd000 ---p 00080000 08:03 1309170                    /lib/libm-2.11.3.so
    7ffff7ddd000-7ffff7dde000 r--p 00080000 08:03 1309170                    /lib/libm-2.11.3.so
    7ffff7dde000-7ffff7ddf000 rw-p 00081000 08:03 1309170                    /lib/libm-2.11.3.so
    7ffff7ddf000-7ffff7dfd000 r-xp 00000000 08:03 1309153                    /lib/ld-2.11.3.so
    7ffff7fe0000-7ffff7fe3000 rw-p 00000000 00:00 0 
    7ffff7ff8000-7ffff7ffb000 rw-p 00000000 00:00 0 
    7ffff7ffb000-7ffff7ffc000 r-xp 00000000 00:00 0                          [vdso]
    7ffff7ffc000-7ffff7ffd000 r--p 0001d000 08:03 1309153                    /lib/ld-2.11.3.so
    7ffff7ffd000-7ffff7ffe000 rw-p 0001e000 08:03 1309153                    /lib/ld-2.11.3.so
    7ffff7ffe000-7ffff7fff000 rw-p 00000000 00:00 0 
    7ffffffea000-7ffffffff000 rw-p 00000000 00:00 0                          [stack]
    ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
    
    Program received signal SIGABRT, Aborted.
    0x00007ffff782d1b5 in raise () from /lib/libc.so.6
    Je vous remercie!

  2. #2
    Membre chevronné
    Inscrit en
    Décembre 2010
    Messages
    290
    Détails du profil
    Informations forums :
    Inscription : Décembre 2010
    Messages : 290
    Par défaut
    Ta fonction ajouter() est effectivement fausse, mais ce n'est pas avec la fonction main() telle que tu la montres ici que tu vas t'en rendre compte, donc il y a peut être AUSSI une erreur dans la fonction detruire().

    Je ne comprends pas trop comment tu as implémenté ta fonction ajouter().
    - Déjà une première chose saute aux yeux : pourquoi un malloc() dont la taille nécessaire (sizeof(cell)) est multipliée par deux ? Mais ceci ne cause pas de corruption, ça alloue juste plus de mémoire que nécessaire.
    - Ensuite, appeler récursivement ajouter() pour ajouter l'élément me parait vraiment bizarre et clairement pas la solution la plus simple.

    Le principe d'un ajout à une liste chainée est le suivant :
    - Allouer la mémoire pour la nouvelle entrée.
    - Initialiser la nouvelle entrée, en particulier faire pointer son champ "suiv" sur la dernière entrée de la liste.
    - Faire pointer la tête de la liste sur la nouvelle entrée.
    Si tu sais traduire ce principe en code C, ta fonction ajouter() fonctionnera.

  3. #3
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 397
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 397
    Par défaut
    faire pointer son champ "suiv" sur la dernière entrée de la liste
    DOES NOT COMPUTE.

    Tu dois décomposer un peu mieux tes fonctions: Je suggère notamment:
    • isoler le remplissage d'une cellule dans une fonction à part
    • la création d'une fonction getDernier() pour arriver facilement à la fin de la liste (plutôt que faire ton appel récursif)

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    cell* creerCellule(int const *table)
    {
    	cell* pc = malloc(sizeof *pc);
    	if(pc != NULL)
    	{
    		size_t i;
    		for(i = 0 ; i<8 ; i++)
    			pc->coordonnees[i] = table[i];
    		pc->suiv = NULL;
    	}
    	return pc;
    }
     
    cell* getDernier(cell* pc)
    {
    	if(pc == NULL)
    		return NULL;
    	while(pc ->suiv != NULL)
    		pc = pc->suiv;
    	return pc;
    }
     
    int ajoutEnFin(cell** ppPremier, cell* pc)
    {
    	if(ppPremier==NULL || pc==NULL)
    		return -1;
    	if(pc->suiv != NULL) /*pc est déjà dans une liste*/
    		return -1;
     
    	if(*ppPremier == NULL) /*la liste est vide*/
    		*ppPremier = pc;
    	else
    	{
    		cell * pDernier = getDernier(*ppPremier);
    		pDernier->suiv = pc;
    	}
     
    	return 0;/*OK*/
    }
     
    int insertionEnTete(cell** ppPremier, cell* pc)
    {
    	if(ppPremier==NULL || pc==NULL)
    		return -1;
    	if(pc->suiv != NULL) /*pc est déjà dans une liste*/
    		return -1;
     
    	pc->suiv = *ppPremier;
    	*ppPremier = pc;
     
    	return 0;/*OK*/
    }
    Pour l'ajout en milieu de liste, tu écriras généralement la fonction insertionApres() (qui est très facile à implémenter) et/ou insertionAvant() (qui l'est moins)
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    int insertionApres(cell* pRef, cell* pc)
    {
    	if(pRef==NULL || pc==NULL)
    		return -1;
    	if(pc->suiv != NULL) /*pc est déjà dans une liste*/
    		return -1;
     
    	pc->suiv = pRef->suiv;
    	pRef->suiv = pc;
     
    	return 0;/*OK*/
    }
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 27
    Par défaut
    D'abord merci pour vos interventions.

    Ensuite j'ai testé la fonction creerCellule() en insérant une unique cellule pour vérifier que l'exécution s'effectue correctement et j'ai un beau

    Segmentation Fault (program exited with code : 139).

    J'ai de même avec des fonctions comme empiler().

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
     
    Robots_tab *R = place_Robot(*p,4);
     
    void updateCoord(Robots_tab *R, coord tab, int nb_rob)
    {
       int k=0,l=0;
       while(k < nb_rob ){
          tab [l] = (*R)[k].x;
          l++;
          tab [l] = (*R)[k].y;
          k++;
          l++;
       }
    }
     
    cell* creerCellule(int const *table)
    {
    	cell* pc = malloc(sizeof *pc);
    	if(pc != NULL)
    	{
    		size_t i;
    		for(i = 0 ; i<8 ; i++)
    			pc->coordonnees[i] = table[i];
    		pc->suiv = NULL;
    	}
    	return pc;
    }
     
    cell *empiler(cell *pc, int const *table) 
    {   
    	int i;
        cell *prem = malloc(sizeof(cell));
        for(i=0; i<8; i++)
           prem->coordonnees[i] = table[i];
        prem->suiv = pc;
        return prem;
    }
     
    cell *depiler(cell *pc) 
    {
        if (pc == NULL)
            return pc;
     
        cell *new = pc->suiv;
        free(pc);
        return new;
    }
     
    void detruire(cell *pc) 
    {
      while (pc != NULL)
        pc = depiler(pc);
    }
     
    main()
    {
        coord init;
        updateCoord(R, init, 4);
        printf("\n%i\n",init[0]);
        printf("%i\n",init[1]);
     
        cell *Rencontres = NULL;
        //Rencontres=creerCellule(init); 
        Rencontres=empiler(Rencontres,init);
        afficher(Rencontres);  
          //      sys_mem_trace();
     
        //printf("MEUUUUUUH");
        //detruire(Rencontres);
    }
    Une suggestion ?

  5. #5
    Modérateur
    Avatar de dinobogan
    Homme Profil pro
    ingénieur
    Inscrit en
    Juin 2007
    Messages
    4 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Activité : ingénieur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 4 073
    Par défaut
    Il y a au moins une erreur ici :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cell* pc = malloc(sizeof *pc);
    Tu alloues une taille de 4 octets (si tu es en 32bits) puis tu fais des opérations d'écritures bien au delà des 4 octets.
    Il faut retirer l'étoile dans le sizeof.

    EDIT : ne pas tenir compte de cette remarque (voir juste après)...
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java
    Que la force de la puissance soit avec le courage de ta sagesse.

  6. #6
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 397
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 397
    Par défaut
    Citation Envoyé par dinobogan Voir le message
    Il y a au moins une erreur ici :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cell* pc = malloc(sizeof *pc);
    Tu alloues une taille de 4 octets (si tu es en 32bits) puis tu fais des opérations d'écritures bien au delà des 4 octets.
    Il faut retirer l'étoile dans le sizeof.
    Euh, c'est l'inverse: C'est si je retire l'étoile que je me retrouve à allouer quatre octets.

    Bon:
    Code bon : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    TYPE* p = malloc(sizeof *p);
    TYPE* p = malloc(sizeof(TYPE)); /*Moins flexible (répétition)*/

    Mauvais:
    Code mauvais : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    TYPE* p = malloc(sizof p);
    TYPE* p = malloc(sizeof(TYPE*));
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

Discussions similaires

  1. Réponses: 12
    Dernier message: 08/02/2005, 23h42
  2. Bibliothèque de listes chainées
    Par gege2061 dans le forum C
    Réponses: 29
    Dernier message: 17/12/2004, 20h15
  3. copie de liste chainée
    Par tomsoyer dans le forum C++
    Réponses: 15
    Dernier message: 31/08/2004, 18h20
  4. Trie liste chaine
    Par Congru dans le forum C
    Réponses: 2
    Dernier message: 30/03/2004, 19h05
  5. tri de liste chainée
    Par RezzA dans le forum C
    Réponses: 7
    Dernier message: 26/01/2003, 20h25

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo