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 :

libération de la mémoire dans un programme C


Sujet :

C

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2012
    Messages : 11
    Points : 8
    Points
    8
    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
    Membre expérimenté Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    Janvier 2009
    Messages
    792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    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 : 792
    Points : 1 481
    Points
    1 481
    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
    "La simplicité ne précède pas la complexité, elle la suit." - Alan J. Perlis
    DVP ? Pensez aux cours et tutos, ainsi qu'à la FAQ !

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2012
    Messages : 11
    Points : 8
    Points
    8
    Par défaut
    si ça serai aussi simple j'en serai très heureux, j'ai besoin de filer un code simplifié donc..
    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
    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
    Membre expérimenté Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    Janvier 2009
    Messages
    792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    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 : 792
    Points : 1 481
    Points
    1 481
    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 ?
    "La simplicité ne précède pas la complexité, elle la suit." - Alan J. Perlis
    DVP ? Pensez aux cours et tutos, ainsi qu'à la FAQ !

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2012
    Messages : 11
    Points : 8
    Points
    8
    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
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    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 expérimenté
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    946
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

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

    Informations forums :
    Inscription : Mars 2006
    Messages : 946
    Points : 1 351
    Points
    1 351
    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
    Homme Profil pro
    Manager / Cyber Sécurité
    Inscrit en
    Mai 2004
    Messages
    10 149
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Manager / Cyber Sécurité

    Informations forums :
    Inscription : Mai 2004
    Messages : 10 149
    Points : 28 116
    Points
    28 116
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    "La route est longue, mais le chemin est libre" -- https://framasoft.org/
    Les règles du forum

  9. #9
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Bonjour,
    Il suffit de lire les premières lignes pour savoir que la mémoire est insuffisamment gérée.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

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

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2012
    Messages : 82
    Points : 132
    Points
    132
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2012
    Messages : 11
    Points : 8
    Points
    8
    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
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    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.

Discussions similaires

  1. Problème de libération de la mémoire dans une fonction
    Par ArnaudFu1 dans le forum Débuter
    Réponses: 2
    Dernier message: 23/02/2012, 16h21
  2. Limite mémoire dans un programme
    Par pascalmagna dans le forum z/OS
    Réponses: 10
    Dernier message: 03/02/2011, 14h33
  3. Détection de faille mémoires dans un programme java
    Par stacre dans le forum Tests et Performance
    Réponses: 3
    Dernier message: 09/02/2009, 12h10
  4. erreur dans la libération de la mémoire
    Par salseropom dans le forum C
    Réponses: 2
    Dernier message: 24/10/2008, 14h57
  5. Réponses: 4
    Dernier message: 01/06/2006, 15h55

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