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 :

Fuite mémoire cherche plombier


Sujet :

C

  1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2011
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juillet 2011
    Messages : 2
    Points : 1
    Points
    1
    Par défaut Fuite mémoire cherche plombier
    Bonjour à tous,

    Je suis confronté à un problème que je n'arrive pas à résoudre, je viens donc humblement vous demander votre aide.

    J'ai fait un programme (pour mon stage) évaluant des opérations logiques (avec des XOR/AND/OR...) d'arité (= nombre d'arguments pris par chaque opérateur) quelconque mais fixe (je veux dire que si j'évalue une fois avec une arité de 3, durant toute l'exécution l'arité sera de 3).

    J'utilise ce programme notamment dans des cas assez particuliers (des permutations circulaires de fonctions XOR, cela est en lien direct avec des réseaux d'automates ou des graphes ou chaque noeud vérifier une fonction XOR d'arité k si ça parle à certains...)

    Le fonctionnement du programme est le suivant:

    -Je lis les opérations souhaitées dans un fichier. les fichiers ont une syntaxe du type XOR ARG1 ARG2 ARG3
    -je les stocke dans une liste
    -je transfère la liste dans un arbre
    -j'évalue cet arbre (à k fils si k est l'arité)
    -je renvoie le résultat en l'écrivant dans un fichier texte

    J'utilise pour simuler mes noeuds (ou automates) des champs de bits (un int donc 32 bits, bien que je n'ai pas eu à aller au delà de 13 bits pour le moment).

    Mon problème est le suivant:
    Lors de l'exécution du programme, j'ai de nombreux malloc/calloc et free (pour générer mes listes, mes arbres...). Je m'efforce de faire un free pour chaque allocation, mais il semblerait que j'en oublie car valgrind m'indique que des bytes sont perdus ou encore alloués:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     HEAP SUMMARY:
    ==7508==     in use at exit: 27,525,120 bytes in 589,824 blocks
    ==7508==   total heap usage: 1,417,220 allocs, 827,396 frees, 61,211,724 bytes allocated
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    LEAK SUMMARY:
    ==7508==    definitely lost: 1,572,856 bytes in 196,607 blocks
    ==7508==    indirectly lost: 25,950,584 bytes in 393,201 blocks
    ==7508==      possibly lost: 1,548 bytes in 14 blocks
    ==7508==    still reachable: 132 bytes in 2 blocks
    ==7508==         suppressed: 0 bytes in 0 blocks
    Toujours d'après valgrind, les bytes ont été alloués par ma fonction de création d'arbre appelée par ma fonction plaçant les valeurs d'une suite dans un arbre. J'ai fait une fonction de suppression d'un arbre qui, lorsque je l'exécute seule dans un fichier à part, semble bien libérer toute la mémoire (valgrind me dit que tout va bien).

    Je ne comprends donc pas d'où viennent ces bytes non libérés, et je viens vous demander votre aide à ce sujet.

    Ci joint mon code commenté, auquel j'ai supprimé les fonctions ne modifiant pas la mémoire. S'il n'est pas clair, je suis ouvert à toute remarque de structuration/présentation/commentaire, ça me fera progresser (c'est le but d'un stage non ?) et essaierai du mieux que je pourrai de vous aider à m'aider.

    Veuillez par ailleurs m'excuser pour toute faute d'orthographe, si je ne poste pas au bon endroit et si mon code est trop long/pas clair/mal fait. C'est la première fois que je demande de l'aide sur un forum, et également la première fois que j'ai à réaliser un "vrai" programme que quelqu'un d'autre devra comprendre et utiliser.


    Merci de votre aide !


    [EDIT]: bon et bien une fois de plus, compiler PUIS modifier le code n'est pas une bonne idée. il manque la fonction "evaluer" pour que le programme puisse marcher, je la rajoute donc bien qu'elle ne soit pas directement intéressante ici
    Fichiers attachés Fichiers attachés

  2. #2
    Membre actif Avatar de brachior
    Homme Profil pro
    Doctorant
    Inscrit en
    Mai 2011
    Messages
    190
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Doctorant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2011
    Messages : 190
    Points : 293
    Points
    293
    Par défaut
    J'ai pas de compilateur au taf, donc je peux pas regarder en détaille.
    Par contre j'ai parcouru la plupart de tes fichiers et si je peux dire 2~3 trucs.
    (à prendre avec des pincettes vu que c'est que de tête ^^)

    // file.c

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    typedef struct ListeRepere{
      Element *debut;
      Element *fin;
      int taille;
    } File;
    Attention, ça peut prêter à confusion voir lever des ambiguïtés =/
    Ta structure File peut être confondue avec le type File des fichiers de la libC.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    if ((nouveau_element = (Element *) malloc (sizeof (Element))) == NULL)
    C'est bien de tester le retour des fonctions de la libC.
    Mais vaut mieux décomposer ton implémentation.
    (on ne cherche plus à gagner de l'espace disque avec un programme ^^)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    nouveau_element = (Element *) malloc (sizeof (Element));
    if (NULL == nouveau_element)
      [...]

    Par contre, même si le cas arrive rarement
    (ou du moins si ça arrive c'est que la machine est tombée ^^)
    Lorsque tu écris :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    if ((nouveau_element = (Element *) malloc (sizeof (Element))) == NULL)
      return -1;
    if ((nouveau_element->donnee = (char *) malloc (4 * sizeof (char))) == NULL)
      return -1;
    Si la deuxième allocation plante, qui libère nouveau_element ?



    // arbres_files.c

    Dans la méthode arbre_t *creer_arbre() là tu ne fais aucun test =/

    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
     
    void supprimerArbre(arbre_t* n)
    {
    //printf("supprimer Arbre ! %p\n",n);
    int k;
      if (n != NULL)
     {
     for(k=0;k<NB_BITS;k++)
     {
      	supprimerArbre(n->fils[k]);
     }
     free(n->fils);
     free(n->val);
     
     }
     free(n);
    }
    Garde la même indentation pour plus de lisibilité ^^
    (vu dans plusieurs fichiers ^^)


    La fonction strtok modifie le premier élément,
    Vu que tu stockes tous les bouts je ne sais pas s'il y a quelque chose a faire pour c et s


    La fonction atoi est déconseillée du fait de sa gestion des erreurs inappropriée.
    (elle retourne 0 si un problème survient, or 0 est aussi un entier valide)
    Il est préférable d'utiliser strtol.


    Je vois plusieurs exit(-1); ...
    Deux choses me chagrine,
    La première, tu utilises une valeur statique au lieu d'une constante.
    La deuxième, tu utilises la fonction exit qui est souvent très mal utilisée.
    N'ayant pas vu de "at_exit" dans ton code, j'en conclue que le programme s'arrête directement sans rien libérer ...
    De plus, cette méthode doit être utilisée par un code "compétent" ou "maitre",
    Une fonction (si son rôle est de l'être) se doit de reporter les erreurs ...
    Elle n'a pas pour rôle d'arrêter le programme.
    Si le report d'erreurs et/ou l'erreur est vraiment énorme,
    Il est fortement conseillé d'utiliser les at_exit pour quitter au plus propre.



    // xor.c

    Même problème que dans "file.c".
    Si l'ouverture de final plante, qui ferme function.
    Des allocations ne sont pas vérifiées non plus ...

  3. #3
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2011
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juillet 2011
    Messages : 2
    Points : 1
    Points
    1
    Par défaut
    Merci de ton aide !

    Je regarde ça et je transmet l'évolution.

    [EDIT]
    j'ai tenté d'appliquer les modifications que tu m'avais dit. Je suis pratiquement certain de pas me servir de on_exit de la bonne manière, mais normalement il n'y a plus de soucis de malloc pas vérifié ou de fclose oublié.

    Par contre ça n'a rien changé à mon problème initial de mémoire...

    Voilà toutefois le code:

    J'ai créé une fonction atoi_ dans un fichier aux.c:
    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
    long int atoi_ (char* s)
    {
    	int errno;
    	char* err=NULL;
    	long int c;
    	c=strtol(s,&err,10);
     
    	if(errno!=0)
    	{
    		//printf("la valeur n'est pas dans l'intervale supporté\n");
    		exit(EXIT_FAILURE);
    	}
     
    	else if(s==err)
    	{
    		//printf("error: no number read, found: %s\n",err);
    		return -1;
    	}
     
    	else
    	{
    		return c;
    	}
     
    }
    J'ai une fonction at_exit passée en argument de on_exit, mais elle est largement perfectible je pense:
    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
    void at_exit (int i,void* a)
    {
    	switch(i)
    	{
    		case 0: printf("Program ended normaly\n");
    		break;
     
    		case 1: fprintf(stderr,"Memory Allocation Error\n");
    		break;
     
    		case 2: fprintf(stderr,"File opening error\n");
    		break;
     
    		case 3: fprintf(stderr,"Invalid arguments error\n");
    		break;
     
    		default: fprintf(stderr,"An unknown error as occured\n");
    	}
    }
    Le reste des modifications se porte sur l'ajout de free ou fclose lors de certaines détections d'erreur et d'une (tentative d') uniformisation des exit/return.
    J'edit mon post initial avec le nouveau code

Discussions similaires

  1. [tomcat][memoire] java.net.URL et fuite mémoire
    Par Seiya dans le forum Tomcat et TomEE
    Réponses: 6
    Dernier message: 09/03/2009, 10h41
  2. Cherche Plombier pour bonne fuite Mémoire!
    Par TNT89 dans le forum C++
    Réponses: 9
    Dernier message: 01/06/2008, 14h10
  3. [Fuites mémoire] Je cherche un utilitaire
    Par 10_GOTO_10 dans le forum C++Builder
    Réponses: 8
    Dernier message: 10/02/2005, 10h03
  4. [SWT]SWT et fuite mémoire(ou pas)
    Par menuge dans le forum SWT/JFace
    Réponses: 2
    Dernier message: 22/06/2004, 21h40
  5. [debug] fuites mémoires
    Par tmonjalo dans le forum C
    Réponses: 3
    Dernier message: 28/07/2003, 17h20

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