Précédent   Forum du club des développeurs et IT Pro > C et C++ > C > Débuter
Débuter Forum d'entraide pour débuter en langage C. Avant de poster -> FAQ C
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 06/12/2012, 21h12   #1
callsty
Invité de passage
 
Inscription : 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?
callsty est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/12/2012, 21h51   #2
plxpy
Membre émérite
 
Avatar de plxpy
 
Homme
Ingénieur
Inscription : janvier 2009
Messages : 494
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 48
Localisation : France, Haute Garonne (Midi Pyrénées)

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

Informations forums :
Inscription : janvier 2009
Messages : 494
Points : 893
Points : 893
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
plxpy est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 06/12/2012, 22h04   #3
callsty
Invité de passage
 
Inscription : octobre 2012
Messages : 10
Détails du profil
Informations forums :
Inscription : octobre 2012
Messages : 10
Points : 4
Points : 4
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;
}
callsty est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/12/2012, 22h14   #4
plxpy
Membre émérite
 
Avatar de plxpy
 
Homme
Ingénieur
Inscription : janvier 2009
Messages : 494
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 48
Localisation : France, Haute Garonne (Midi Pyrénées)

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

Informations forums :
Inscription : janvier 2009
Messages : 494
Points : 893
Points : 893
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 ?
plxpy est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 06/12/2012, 22h18   #5
callsty
Invité de passage
 
Inscription : octobre 2012
Messages : 10
Détails du profil
Informations forums :
Inscription : octobre 2012
Messages : 10
Points : 4
Points : 4
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
callsty est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/12/2012, 00h52   #6
koala01
Modérateur
 
Avatar de koala01
 
Philippe Dunski
Inscription : octobre 2004
Messages : 8 628
Détails du profil
Informations personnelles :
Nom : Philippe Dunski
Âge : 41

Informations forums :
Inscription : octobre 2004
Messages : 8 628
Points : 13 351
Points : 13 351
Envoyer un message via MSN à koala01 Envoyer un message via Skype™ à koala01
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
je ne répondrai à aucune question technique par E-mail, message visiteur ou message privé
Vous avez obtenu votre réponse pensez au bouton en bas de page
koala01 est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 07/12/2012, 08h10   #7
pfeuh
Membre Expert
 
Développeur en systèmes embarqués
Inscription : mars 2006
Messages : 763
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 : 763
Points : 1 031
Points : 1 031
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
pfeuh est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/12/2012, 08h27   #8
gangsoleil
Modérateur
 
Avatar de gangsoleil
 
R&D en systemes informatiques bas niveau Unix/Linux
Inscription : mai 2004
Messages : 7 191
Détails du profil
Informations personnelles :
Âge : 32
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 : 7 191
Points : 18 088
Points : 18 088
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
gangsoleil est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/12/2012, 10h30   #9
leternel
Expert Confirmé
 
Homme Pierre
Ingénieur développement logiciels
Inscription : juin 2007
Messages : 1 220
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 220
Points : 2 596
Points : 2 596
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.
leternel est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/12/2012, 10h43   #10
DrDarko
Membre habitué
 
Homme Allan
Étudiant
Inscription : août 2012
Messages : 82
Détails du profil
Informations personnelles :
Nom : Homme Allan
Âge : 23
Localisation : France, Yvelines (Île de France)

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : août 2012
Messages : 82
Points : 146
Points : 146
Citation:
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 :

Citation:
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...
DrDarko est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 25/12/2012, 10h00   #11
callsty
Invité de passage
 
Inscription : octobre 2012
Messages : 10
Détails du profil
Informations forums :
Inscription : octobre 2012
Messages : 10
Points : 4
Points : 4
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.

Citation:
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.

Citation:
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
Citation:
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
callsty est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 25/12/2012, 16h08   #12
koala01
Modérateur
 
Avatar de koala01
 
Philippe Dunski
Inscription : octobre 2004
Messages : 8 628
Détails du profil
Informations personnelles :
Nom : Philippe Dunski
Âge : 41

Informations forums :
Inscription : octobre 2004
Messages : 8 628
Points : 13 351
Points : 13 351
Envoyer un message via MSN à koala01 Envoyer un message via Skype™ à koala01
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
je ne répondrai à aucune question technique par E-mail, message visiteur ou message privé
Vous avez obtenu votre réponse pensez au bouton en bas de page
koala01 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Cette discussion est résolue.
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 04h53.


 
 
 
 
Partenaires

Hébergement Web