Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 12 sur 12
  1. #1
    Invité de passage
    Inscrit en
    octobre 2012
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : octobre 2012
    Messages : 10
    Points : 4
    Points
    4

    Par défaut libération de la mémoire dans un programme C

    Bonjour,
    J'ai créé un programme informatique qui utilise en permanence des malloc et des free. Bien évidement j'ai utilisé Valgrind pour repérer les fuites mémoires et les enlever, jusqu'à obtenir zéro fuites. Jusque là l'histoire est sans problème mais en jetant un petit coup d'oeil sur le moniteur système je me suis aperçu que mon programme ne fait que grignoter la mémoire au fur et à mesure du temps.
    La question est simple: comment ça se fait?

  2. #2
    Modérateur
    Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    janvier 2009
    Messages
    598
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur géographe
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : janvier 2009
    Messages : 598
    Points : 961
    Points
    961

    Par défaut

    Bonjour,

    la réponse est tout aussi simple. Puisque tu certifies qu'il n'y a pas de fuite mémoire, et bien c'est parce que tu alloues, au fil du temps, dans ton programme informatique, de plus en plus de mémoire.

    CQFD

  3. #3
    Invité de passage
    Inscrit en
    octobre 2012
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : octobre 2012
    Messages : 10
    Points : 4
    Points
    4

    Par défaut

    si ça serai aussi simple j'en serai très heureux, j'ai besoin de filer un code simplifié donc..
    Code :
    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
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
     
    int main()
    {
        //Déclaration des variables
        //blabla
     
     
        //DEBUT DU PROGRAMME
        while (continuer==1)
        {
            //Allocation mémoire pour le premier dictionnaire
            pdictionnaire = (TDictionnaire)malloc(sizeof(Dictionnaire));
            //initialisation des pointeurs
            pdictionnaire -> nextModele = NULL;
            pdictionnaire_prec = NULL;
     
            //Allocation mémoire de la tête de ligne pour la base de données (séquences d´ADN lues à partir d´un fichier source)
            tete_ligne = (TLigne)malloc(sizeof(Ligne));
            //Initialisation des pointeurs
            tete_ligne -> nextLig = NULL;
            tete_ligne -> tab = NULL;
     
            nb_seq = mise_en_memoire_fichier ( tete_ligne); //on récupère le nombre de séquences à traiter
            if ( nb_seq > 1 )   //il faut au moins deux séquences pour pouvoir les comparer
    		{
                valeur_1_seq_quorum = 100. / nb_seq;    //calcul de la part jouée par chaque séquence au niveau du quorum
                afficher_les_sequences_du_fichier( tete_ligne );
     
                //Saisies par l´utilisateur
               //blabla
     
                //
    			pdictionnaire_prec = NULL;   //on ne peut pas remonter avant le dictionnaire initial (de taille 0)
    			compteur = 0;
    			creer_dictionnaire_initial ( tete_ligne, pdictionnaire, k, nb_seq);
    			tete_pstructthread = NULL;  //initialisation de la liste chaînée pour les threads (voir dans la partie concernée)
     
    			if ( taille_max > 0 )   //Recherche d´un motif commun d´au moins une caractère
    			{
    			    tete_pstructthread = thread_structure_initialisation_noyau( tete_pstructthread, nb_thread, k, quorum, valeur_1_seq_quorum, tete_ligne, nb_seq);
    			}
     
    			while ( pdictionnaire -> taille < taille_max && compteur != 1 ) //tant que l´on a pas atteint la taille maximale du dictionnaire et que
    			{
                    compteur = 1;
    				//on regarde si on a des occurrences dans le dictionnaire originel
    				//cela demande une vérification énorme lorsque l'on supprime les mots dans le dico pour répondre au quorum
    				if ( pdictionnaire -> nextModele != NULL )  //le dictionnaire contient au moins un modèle
    				{
    				    compteur = 0;   //compteur ne vaudra 0 que s´il reste des modèles à traiter et 1 dans le cas contraire
    					if ( pdictionnaire_prec != NULL)    //la taille du dictionnaire est supérieure à 0
    					{
    						supprimer_dictionnaire(pdictionnaire_prec); //suppression de l'ancien dictionnaire de taille n-1
    						//pensez à supprimer le dictionnaire précédent et l'autre dictionnaire à la fin de la boucle, et du coup enregistrer la/les bonnes réponses
    					}
    					printf("Longueur du dictionnaire en cours. %hd\n", pdictionnaire -> taille +1 );    //Permet de suivre l´avancée du programme pour des calculs complexes
    					pdictionnaire_prec = pdictionnaire; //actualisation du dictionnaire précédent
    					pdictionnaire=(TDictionnaire) malloc (sizeof (Dictionnaire));   //allocation mémoire du nouveau dictionnaire
    					traitement_creation_motifs_appel_thread (pdictionnaire_prec, pdictionnaire, tete_ligne, tete_pstructthread);//création motifs dans le dictionnaire
    				}
    			}
     
                //Mécanisme de secours si pas extension du modèle jusqu'à la taille demandée
                if ( pdictionnaire -> nextModele != NULL )  //Si le dictionnaire actuel contient au moins un modèle, alors
                {
     
                    if ( pdictionnaire_prec != NULL)    //Si l´utilisateur n´a pas demandé un dictionnaire de taille 0, alors
                    {
                        supprimer_dictionnaire(pdictionnaire_prec); //suppression du dictionnaire précédent
                    }
                }
    			else
    			{
    			    //le dictionnaire actuel ne contient aucun modèle, on a donc pas pu étendre le dictionnaire à la taille souhaitée
    			    supprimer_dictionnaire(pdictionnaire);  //on supprime alors le dictionnaire vide...
    			    pdictionnaire = pdictionnaire_prec;     //...et on revient au dictionnaire précédent, qui constitue le plus grand dictionnaire possible et donc la meilleure solution
    			}
     
     
    			//Demande si sauvegarde dans un fichier
    			printf("\nVoulez-vous sauvegarder les résultats obtenus dans un fichier (resultat.txt)? \n");
    			printf("Tapez 1 pour oui \n");
    			printf("Tapez 0 pour non \n");
    			scanf("%d", &choix_enregistrer );
     
    			//Affichage des résultats obtenus
    			afficher_enregistrer_dictionnaire ( pdictionnaire, taille_max, k, tete_ligne, choix_enregistrer );
     
    			supprimer_dictionnaire(pdictionnaire);//Suppression du dictionnaire pour libérer l´espace mémoire alloué
    			if ( tete_pstructthread != NULL)
    			{
    			    thread_structure_noyau_suppression( tete_pstructthread ); 
    			}
    		}
    		else
    		{
                        //blabla
    		}
    		supprimer_bdd (tete_ligne);
            printf("Voulez-vous charger un autre fichier? \n");
            printf("Tapez 1 pour oui \n");
            printf("Tapez 0 pour non \n");
            scanf("%d", &continuer );
            if ( continuer == 0 )   //sortie du programme
            {
                printf("\nMerci d'avoir utilisé notre programme... Et à bientôt!!!\n");
    		}
        }
    return 0;
    }

  4. #4
    Modérateur
    Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    janvier 2009
    Messages
    598
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur géographe
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : janvier 2009
    Messages : 598
    Points : 961
    Points
    961

    Par défaut

    Je n'ai aucune envie de parcourir tes lignes de code.

    Ce que je voulais dire c'est que, si tu es sur que tu n'as pas de fuite mémoire, que tu as, malgré tout, un "problème" de mémoire, le C, l'OS ne sont pas les premières choses à soupçonner.

    Même après 25 ans de développement en C, quand mon programme merde, c'est moi que je remets en cause. Je n'ai pas la réaction de dire que c'est le compilo qui a des bugs ou l'OS qui part en vrille.

    Donc, quand dans ton message initial, tu dis que tout est nickel et que ça ne marche pas, qu'attends-tu comme réponse ? Qu'imagines-tu qu'on puisse te dire ?

  5. #5
    Invité de passage
    Inscrit en
    octobre 2012
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : octobre 2012
    Messages : 10
    Points : 4
    Points
    4

    Par défaut

    dans mon premier message, je voulais juste comprendre. Même si je suis d'accord que je n'ai pas bien fait toutes les choses, je voulais de l'aide pour savoir d'où ça peut venir mais surtout trouver des pistes car en ce moment j'ai épuisé les solutions qui venaient à moi

  6. #6
    Modérateur
    Avatar de koala01
    Profil pro Philippe Dunski
    Inscrit en
    octobre 2004
    Messages
    9 691
    Détails du profil
    Informations personnelles :
    Nom : Philippe Dunski
    Âge : 42

    Informations forums :
    Inscription : octobre 2004
    Messages : 9 691
    Points : 15 768
    Points
    15 768

    Par défaut

    Salut,

    Personnellement, je pense que 110 ligne pour une fonction en en ayant retiré je ne sais combien pour les remplacer par blabla, c'est au moins quatre fois de trop...

    Peut etre devrais tu déjà essayer de faire en sorte de diviser cette fonction en une série de petite fonctions qui ne prennent qu'un aspect en charge, mais qui s'en occupent bien

    A partir de là, il te sera beaucoup plus facile de trouver "où le bat blesse" et d'y apporter une solution
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  7. #7
    Membre Expert
    Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    mars 2006
    Messages
    838
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : Industrie

    Informations forums :
    Inscription : mars 2006
    Messages : 838
    Points : 1 064
    Points
    1 064

    Par défaut

    Salut,

    Citation Envoyé par koala01 Voir le message
    diviser cette fonction en une série de petite fonctions qui ne prennent qu'un aspect en charge, mais qui s'en occupent bien
    Et pour être sûr qu'elles s'en occupent bien, faire quelques tests unitaires dessus... D'ailleurs étant sous windows, je ne peux pas utiliser Valgrind, mais un test unitaire sur une fonction qui alloue et désalloue des millions de fois une structure ou autre chose, ça m'a toujours bien aidé pour trouver les fuites mémoire dont j'ai été responsable.

    A+

    Pfeuh

  8. #8
    Modérateur
    Avatar de gangsoleil
    Profil pro
    R&D en systemes informatiques bas niveau Unix/Linux
    Inscrit en
    mai 2004
    Messages
    8 495
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : R&D en systemes informatiques bas niveau Unix/Linux

    Informations forums :
    Inscription : mai 2004
    Messages : 8 495
    Points : 21 642
    Points
    21 642

    Par défaut

    Citation Envoyé par callsty Voir le message
    Bien évidement j'ai utilisé Valgrind pour repérer les fuites mémoires et les enlever, jusqu'à obtenir zéro fuites. Jusque là l'histoire est sans problème mais en jetant un petit coup d'oeil sur le moniteur système je me suis aperçu que mon programme ne fait que grignoter la mémoire au fur et à mesure du temps.
    La question est simple: comment ça se fait?
    Alors je ne sais pas ce que tu as simplifie dans ton programme, mais :

    Code :
    1
    2
    3
    4
    /tmp> grep -ic malloc dev.c
    3
    /tmp> grep -ic free dev.c
    0
    Tu as 3 allocations memoire pour 0 free. C'est ca que tu appelles 0 fuite ?

    sinon, en vrac :
    • Pas de test de code de retour de malloc
    • code non compilable
    • scanf sur les entrees clavier a proscrire
    Modérateur "C", "Informatique Générale & Hardware" et "Unix"
    Les règles du forum

  9. #9
    Expert Confirmé Sénior
    Homme Profil pro Pierre
    Ingénieur développement logiciels
    Inscrit en
    juin 2007
    Messages
    1 967
    Détails du profil
    Informations personnelles :
    Nom : Homme Pierre
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : juin 2007
    Messages : 1 967
    Points : 4 146
    Points
    4 146

    Par défaut

    Bonjour,
    Il suffit de lire les premières lignes pour savoir que la mémoire est insuffisamment gérée.
    Code :
    1
    2
    3
    pdictionnaire = (TDictionnaire)malloc(sizeof(Dictionnaire));
    //initialisation des pointeurs
    pdictionnaire -> nextModele = NULL;
    Que se passe-t-il si le malloc échoue?

    Par conséquent, ton programme est nécessairement faux.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • La plus sotte des questions est celle qu'on ne pose pas.

    Pour faire des graphes, essayez yEd.

  10. #10
    Membre habitué
    Homme Profil pro Allan
    Étudiant
    Inscrit en
    août 2012
    Messages
    82
    Détails du profil
    Informations personnelles :
    Nom : Homme Allan
    Âge : 24
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : août 2012
    Messages : 82
    Points : 119
    Points
    119

    Par défaut

    Personnellement, je pense que 110 ligne pour une fonction en en ayant retiré je ne sais combien pour les remplacer par blabla, c'est au moins quatre fois de trop...
    koala01 +1

    Après j'ai 2 -3 autres remarques :

    Tu as 3 allocations memoire pour 0 free. C'est ca que tu appelles 0 fuite ?
    Comme l'a remarqué gangsoleil, dans ton code on peut voir 3 malloc dont un dans une boucle... Et après tu nous dis : c'est la que j'appelle une fonction qui libère la mémoire. Vu que tu as un problème de mémoire à mon avis ça vient de ces fonctions qui libèrent mal ta mémoire...


    Pourquoi à chaque tour de boucle vérifier si continuer est égal à 0 et si c'est le cas tu affiches un message puis tu sors de ta boucle...?

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    int main()
    {
        while (continuer==1)
        {
            if ( continuer == 0 )   //sortie du programme
                printf("\nMerci d'avoir utilisé notre programme... Et à bientôt!!!\n");
        }
    return 0;
    }
    Autant le sortir de la boucle. Que se passe t'il si je rentre 4...?

    Je pense qu'il y a beaucoup de truc à revoir en commençant par découper ton code vérifier, tes retours de fonctions...

  11. #11
    Invité de passage
    Inscrit en
    octobre 2012
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : octobre 2012
    Messages : 10
    Points : 4
    Points
    4

    Par défaut

    Désolé d'avoir donné un code totalement incomplet, je vous ai dit qu'avec valgrind je n'avais zéro fuite de mémoire et cela est vrai. L'explication de comment ça se fait que? c'est qu'il existe des fonctions de suppressions qui supprime les têtes de listes créés dans le main.

    Que se passe t'il si je rentre 4...?
    Le projet que j'ai construit ne s'appuyait pas sur un utilisateur fou car cela n'était pas le sujet. Les printf que tu n'as pas copier coller était pourtant bien utile pour éviter ça...

    Donc au final je vous rassure mes fonctions font de jolies choses dans le meilleur des mondes, je fait tout bien avec mes suppressions et mes allocations. A par qu'il est vrai et merci de l'avoir fait remarqué que mes fonctions sont trop grosses pour certaines et que j'aurai pu optimiser plus finement mon code.

    Bonjour,

    la réponse est tout aussi simple. Puisque tu certifies qu'il n'y a pas de fuite mémoire, et bien c'est parce que tu alloues, au fil du temps, dans ton programme informatique, de plus en plus de mémoire.

    CQFD
    Je n'ai aucune envie de parcourir tes lignes de code.

    Ce que je voulais dire c'est que, si tu es sur que tu n'as pas de fuite mémoire, que tu as, malgré tout, un "problème" de mémoire, le C, l'OS ne sont pas les premières choses à soupçonner.

    Même après 25 ans de développement en C, quand mon programme merde, c'est moi que je remets en cause. Je n'ai pas la réaction de dire que c'est le compilo qui a des bugs ou l'OS qui part en vrille.

    Donc, quand dans ton message initial, tu dis que tout est nickel et que ça ne marche pas, qu'attends-tu comme réponse ? Qu'imagines-tu qu'on puisse te dire ?
    L'OS est une chose a soupçonner, ce qui était mon cas. Valgrind fait bien les choses encore une fois...

    En tout cas merci d'avoir essayé de résoudre mon problème.
    Les raisons qui font que l'os ne récupère pas la mémoire libérée est en cours de résolution sur ce nouveau topic.
    http://www.developpez.net/forums/d12...t/#post7040121

  12. #12
    Modérateur
    Avatar de koala01
    Profil pro Philippe Dunski
    Inscrit en
    octobre 2004
    Messages
    9 691
    Détails du profil
    Informations personnelles :
    Nom : Philippe Dunski
    Âge : 42

    Informations forums :
    Inscription : octobre 2004
    Messages : 9 691
    Points : 15 768
    Points
    15 768

    Par défaut

    Citation Envoyé par callsty Voir le message
    Le projet que j'ai construit ne s'appuyait pas sur un utilisateur fou car cela n'était pas le sujet. Les printf que tu n'as pas copier coller était pourtant bien utile pour éviter ça...
    Faux...

    Quel que soit le code, le premier sujet est d'être un minimum "idiot proof", dans le sens où 90% des bugs trouvent leur origine entre le clavier et la chaise.

    Le fait de s'assurer qu'une entrée utilisateur est cohérente avec ce que l'on attend se doit d'être intégré dans ton système global de pensée car ce n'est qu'en gardant à l'esprit que l'utilisateur est un "imbécile distrait" que toute la logique pourra effectivement s'appliquer
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

+ Répondre à la discussion
Cette discussion est résolue.

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •