Pb:fuite memoire en language c

Résolu
PADYVEN Messages postés 69 Date d'inscription lundi 10 février 2003 Statut Membre Dernière intervention 29 août 2012 - 23 janv. 2008 à 09:35
PADYVEN Messages postés 69 Date d'inscription lundi 10 février 2003 Statut Membre Dernière intervention 29 août 2012 - 28 janv. 2008 à 09:51
Bonjour ,

voila je devellope une liste double pour apprendre le c
rien ne vaut la pratique
j'ai 3 fonctions une pour creer la liste ,une pour inserer un element ,une pour supprimer la liste
le probleme c'est que j'ai une fuite de memoire mais je n'arrive pas a comprendre pourquoi ci-joint le code d'utilisation et les bout de code utilisé pour la liste
les printf sont ceux que j'ai utilisé pour debugger

Ps :merci d'etre tres explicatif parce que la je pense etre pas tres tres bon
MERCI BEAUCOUP

//*******************************
//utilisation
//*******************************
void testlist()
{
    int toto=0;
    ListeDouble *malist;
    system("cls");
    printf("creation de la Liste\n");
    system("Pause");
    malist=CreateListD();
    if (malist!=NULL)
    {
        //test deux methode pour le nombre d'element
        printf("Liste cree avec %ld element\n",malist->NbElements);
        //insert 10000 elements
        printf("Insertion des elements\n");
        system("Pause");
        for (toto=0;toto<10;toto++)
        {
        //ajout un element
        InsertListD(malist,toto);
        }
        printlist(malist);
        printf("Efface la liste\n");
        system("Pause");
        ClearListD (&malist);
        printf("Fin avant sortie\n");
        system("Pause");
    }
}

//*******************************
//Structures
//*******************************

//Structure noeud
typedef struct Node Node;   //taille 12 octets
struct Node
{
    Node *Prev;
    Node *Next;
    unsigned long int *Data;
};


//Structure liste
typedef struct ListeDouble ListeDouble;  //taille 16 octets
struct ListeDouble
{
    Node *First;     //adresse du premier noeud
    Node *Last;      //adresse du noeud de fin
    Node *NoeudTravail;      //adresse du noeud de fin
    unsigned long int NbElements;   //Nombre d'elements
};

//*******************************
//Codes de gestion
//*******************************
/*-------------------------------
Nouvelle liste
Renvoi un pointeur de type liste double
---------------------------------*/
//premier noeud precedant=NULL
//dernier noeud suivant=NULL
ListeDouble *CreateListD (void)
{
    ListeDouble *P_ListD = malloc (sizeof (ListeDouble));
    if (P_ListD)
    {//memoire alloué
     //initialisation de la liste
        P_ListD->First = NULL;
        P_ListD->Last = NULL;
        P_ListD->NbElements=0;
    }
    else
    {
        fprintf (stderr, "Memoire insufisante\n");
        exit (EXIT_FAILURE);
    }
    return P_ListD;
}

/*-------------------------------
Insert un element
---------------------------------*/
//insert suivant data
void InsertListD (ListeDouble *P_ListD, unsigned long int *Data)
{
    if (P_ListD)
    {//si pointeur sur liste non nul
        //P_NoeudTemp nouveau noeud a insere
        Node *P_NoeudTemp = NULL;
        P_NoeudTemp = malloc (sizeof (Node));
        if (P_NoeudTemp!=NULL)
        {
            //set les data
            P_NoeudTemp->Data = Data;
            if (P_ListD->First == NULL)
            {//premiere insertion dans la liste
                P_ListD->First = P_NoeudTemp;
                P_NoeudTemp->Prev = NULL;
                P_NoeudTemp->Next = NULL;
            }
            else
            {//recherche le noeud a inserer
                //P_NoeudRecherche le noeud pour parcourir la liste setter au debut
                Node *P_NoeudRecherche = P_ListD->First;
                while(P_NoeudRecherche->Next)
                {  //tant que le suivant n'est pas null
                   P_NoeudRecherche=P_NoeudRecherche->Next;
                }
                //remplace le noeud suivant
                P_NoeudTemp->Prev=P_NoeudRecherche;
                P_NoeudTemp->Next=P_NoeudRecherche->Next;
                P_NoeudRecherche->Next=P_NoeudTemp;
            }
            //increment le nombre d'element
            P_ListD->NbElements++;
        }
        else
        {
            fprintf (stderr, "Memoire insuffisante\n");
            exit (EXIT_FAILURE);
        }
    }
}

/*-------------------------------
Efface la liste double
---------------------------------*/
void ClearListD (ListeDouble ** P_ListD)
{   //efface la liste ** P_ListD car on doit modifier le pointeur de liste envoyé
    if (P_ListD!=NULL)
    {
        //Efface les elements recursivement
        node_clear_r((*P_ListD)->First);
        //supprime la liste
        free (P_ListD);
        *P_ListD = NULL;
    }
}


/*-------------------------------
Efface les elements recursivement
---------------------------------*/
void node_clear_r (Node *p_node)
{
   if (p_node != NULL)
   {
      node_clear_r (p_node->Next);
      printf("Element effacé adresse:%p\n",p_node);
      free (p_node);
   }
}




/*-------------------------------
Affiche la liste sur la sortie standard
---------------------------------*/
void printlist(ListeDouble *liste)
{
    int toto=0;
    Node *PP;


    printf("Liste cree avec %ld element\n",liste->NbElements);
    PP=liste->First;
    for (toto=0;toto<liste->NbElements;toto++)
    {
        printf("Element %d (valeur %ld) Adresse:%p\n\tAdresse prec:%p \n\tAdresse next:%p\n",toto,PP->Data,PP,PP->Prev,PP->Next);
        printf("\n");
        PP=PP->Next;
    }
    printf ("\n");
}

10 réponses

PADYVEN Messages postés 69 Date d'inscription lundi 10 février 2003 Statut Membre Dernière intervention 29 août 2012
28 janv. 2008 à 09:51
merci beaucoup
a tous
bye :-)
3
cs_juju12 Messages postés 966 Date d'inscription samedi 3 avril 2004 Statut Membre Dernière intervention 4 mars 2010 4
23 janv. 2008 à 18:41
Dans ClearListID :
free(*P_ListD) au lieu de  free (P_ListD);
à moins que c'était une erreur de copie?

Dans InsertListID :
 P_NoeudTemp->Next=NULL; au lieu de  P_NoeudTemp->Next=P_NoeudRecherche->Next;

sinon, comment sais-tu que tu as une fuite mémoire?
0
nickydaquick Messages postés 416 Date d'inscription vendredi 31 janvier 2003 Statut Membre Dernière intervention 19 décembre 2013 3
23 janv. 2008 à 20:27
Salut 2 Erreurs;
1- ta boucle for tu utilises des int que tu passes par VALEUR a la fonction InsertListD qui requiert que le parametre 2 soit passe par ADRESSE, et ce qui est drole ce que tous tes noeuds vont donc pointer a la meme adresse , heureusement que tu ne detruis pas la memoire pointee par le noeud

2-dans la fonction ClearListD tu passes une adresse du pointeur de liste : parfait
l'erreur , il faut verifier aussi que *P_ListD!=NULL,
et lorsque tu liberes la liste : free(*P_ListD);
les fonctions recursives , non pas vraiment :

if((*P_ListD)->First)
{
    while((*P_ListD)->First->Next)
    {
       (*P_ListD)->First->Prev = (*P_ListD)->First->Next;
      (*P_ListD)->First->Next = (*P_ListD)->First->Prev->Next;
       free( (*P_ListD)->First->Prev);
    }
    free((*P_ListD)->First);
}

je suis heureux de faire partie d'une grande famille ...!
0
nickydaquick Messages postés 416 Date d'inscription vendredi 31 janvier 2003 Statut Membre Dernière intervention 19 décembre 2013 3
23 janv. 2008 à 20:30
Salut,
dans l'erreur 1 , je voulais dire si tu passais correctement l'argument par ADRESSE tous les pointeurs de la liste aurait la meme adresse comme DATA, mais en le laissant tel quel, le valeur de toto (0,1,2,....) va etre consideree comme l'adresse d'un emplacement memoire ( a priori invalide)==crash lors de l'acces;

je suis heureux de faire partie d'une grande famille ...!
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
PADYVEN Messages postés 69 Date d'inscription lundi 10 février 2003 Statut Membre Dernière intervention 29 août 2012
24 janv. 2008 à 08:54
salut,

donc j'ai corriger les erreurs que vous m'avez idinqué, c'est mieux
mais je crois que ca fuit toujours un petit peu

pour tester les fuites j'ai deux methodes
la bourrin:
    -des system("Pause"); avant l'insertion et avant le delete et ma boucle d'insertion comporte 10000 elements et je regarde avec le TASK manager de windows
l'util memoire de mon appli

sinon la plus fine
j'utilise les printf du programme pour verifier si avec deux utilisations de TestList j'utilise les memes adresses memoires pour les noeud et pour la liste

donc quand je dis que c'est mieux, je vois avec la deuxieme methode que j'utilise les meme adresse memoires mais pas dans le meme ordre
et avec la deuxieme methode mon appli fait 1208ko en memoire  avant l'insertion des elements (10000 elements)      1448ko apres   et 1268 apres la suppression
j'aurais donc logiquement une fuite de 40ko

donc c'est toujours pas parfait
0
Spiffou Messages postés 100 Date d'inscription jeudi 1 avril 2004 Statut Membre Dernière intervention 9 juin 2014 1
24 janv. 2008 à 16:54
une technique simple pour détecter rapidement une fuite mémoire:

ajoute un tableau de double (car ca prend plus de place en mémoire) dans ta structure node
struct Node
{
    Node *Prev;
    Node *Next;
    unsigned long int *Data;
    double buff[20000];   // tu peux encore augmenter la taille du tableau pour que la fuite sois plus voyante
};

de cette façon il y aura une fuite bien visible en cas de non désallocation d'une partie des noeux.

bon courage
0
PADYVEN Messages postés 69 Date d'inscription lundi 10 février 2003 Statut Membre Dernière intervention 29 août 2012
25 janv. 2008 à 01:49
quelqu'un pourrait m'expliquer pourquoi mes elements apres la deuxieme allocation n'utilise pas la place memoire dans le meme ordre
si mon programme ne fais rien d'autre ca devrait etre le cas non?

sinon je remetrait la liste a jour prochainement.

merci
0
nickydaquick Messages postés 416 Date d'inscription vendredi 31 janvier 2003 Statut Membre Dernière intervention 19 décembre 2013 3
25 janv. 2008 à 09:22
Salut,
veux tu qu'on te donne un exemple de liste doublement chainee en C?
la ca pourra t'aider , tu compareras et voila.
je suis heureux de faire partie d'une grande famille ...!
0
PADYVEN Messages postés 69 Date d'inscription lundi 10 février 2003 Statut Membre Dernière intervention 29 août 2012
25 janv. 2008 à 10:43
oui pourquoi pas
merci beaucoup
j'ai deja telechargé beaucoup d'exemples mais avec des noms pas toujours explicite ou pas de commentaires des fois c'est difficille
je vais utiliser cette liste dans un cas tres particulier elle doit etre tres rapide pour l'insertion et ce sera une insertion triee
0
nickydaquick Messages postés 416 Date d'inscription vendredi 31 janvier 2003 Statut Membre Dernière intervention 19 décembre 2013 3
25 janv. 2008 à 18:00
Salut,
bon vite fait en C , ton code retape. J'ai laisse tes commentaires en place, modifie quelque peu le nom des fonctions et procedures. Test it and if possible, enjoy it then

//*******************************
//Structures
//*******************************

//Structure noeud
typedef struct Node
{
    Node *Prev;
    Node *Next;
    unsigned long Data;
}Node, *PNode;

//Structure liste
typedef struct DList
{
    Node *Root;     //adresse du premier noeud
    unsigned long Size;   //Nombre d'elements
}DList,*PDList;

//*******************************
//Signature des fonctions
//*******************************
DList *CreateDList();
const char InsertInDList (DList*, const unsigned long);
void FreeDList (DList** );
void printDList(DList*);

//*******************************
//utilisation
//*******************************
void testlist()
{
    unsigned long toto=0;
    PDList list;
    system("cls");
    printf("creation de la Liste\n");
    system("Pause");
    list=CreateDList();
    if(list)
    {
        //test deux methode pour le nombre d'element
        printf("Liste cree avec %ld element\n",list->Size);
        //insert 10elements
        printf("Insertion des elements\n");
        system("Pause");
        for(toto=0;toto<10;++toto)
        {
        //ajout un element
            if(!InsertInDList(list,toto))printf("Erreur-Insertion element : %i",toto);
        }
        printDList(list);
        printf("Efface la liste\n");
        system("Pause");
        ClearDList (&list);
        printf("Fin avant sortie\n");
        system("Pause");
    }
}

/*******************************
//Codes de gestion
//*******************************

/*-------------------------------
Nouvelle liste
Renvoi un pointeur de type liste double
---------------------------------*/

DList *CreateDList()
{
    PDList P_ListD = malloc(sizeof (DList));
    if (P_ListD)
    {//memoire alloué
     //initialisation de la liste
        P_ListD->Root = 0;
        P_ListD->Size = 0;
    }
    else
        fprintf (stderr, "Memoire insufisante\n");

    return P_ListD;
}

/*-------------------------------
Insert un element
---------------------------------*/

const char InsertInDList (DList *P_ListD, const unsigned long Data)
{
    if (P_ListD)
    {//si pointeur sur liste non nul
        //P_NoeudTemp nouveau noeud a insere
        PNode P_NoeudTemp = malloc (sizeof (Node));
        if(!P_NoeudTemp)
        {
            //set les data
            P_NoeudTemp->Data = Data;            P_NoeudTemp->Prev P_NoeudTemp->Next 0;
            if (!P_ListD->First)
            //premiere insertion dans la liste
                P_ListD->First = P_NoeudTemp;
      
            else
            {//recherche le noeud a inserer
                //P_NoeudRecherche le noeud pour parcourir la liste setter au debut
                PNode P_NoeudRecherche = P_ListD->First;
                while(P_NoeudRecherche->Next)
                    //tant que le suivant n'est pas null
                    P_NoeudRecherche=P_NoeudRecherche->Next;
                //remplace le noeud suivant
                P_NoeudTemp->Prev=P_NoeudRecherche;
                P_NoeudRecherche->Next=P_NoeudTemp;
            }
            //increment le nombre d'element
            ++P_ListD->Size;
        }
        else
        {
            fprintf (stderr, "Memoire insuffisante\n");
            return 0;//failure, no item inserted
        }
    }
    return 1;//success , one item inserted
}

/*-------------------------------
Efface la liste double
---------------------------------*/
void ClearDList (DList** P_ListD)
{   //efface la liste ** P_ListD car on doit modifier le pointeur de liste envoyé
    if (P_ListD && *P_ListD)
    {
        //Efface les elements recursivement
        while((*P_ListD)->First->Next)
        {
            (*P_ListD)->First->Prev = (*P_ListD)->First->Next;
            (*P_ListD)->First->Next = (*P_ListD)->First->Next->Next;
            free((*P_ListD)->First->Prev);
        }
        free((*P_ListD)->First);
        //supprime la liste
        free (*P_ListD);
        *P_ListD = NULL;
    }
}

/*-------------------------------
Affiche la liste sur la sortie standard
---------------------------------*/
void printDList(DList *liste)
{
    unsigned long toto=0;
    PNode PP;

    if(!liste)return;
   
    printf("Liste cree avec %ld element\n",liste->Size);
    PP=liste->First;
    while(PP)
    {
    printf("Element %d (valeur %ld) Adresse:%p\n\tAdresse prec:%p \n\tAdresse next:%p\n\n",(toto++),PP->Data,PP,PP->Prev,PP->Next);
        PP=PP->Next;
    }
    printf ("\n");
}

J'espere avoir aide, salut
je suis heureux de faire partie d'une grande famille ...!
0
Rejoignez-nous