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 :

éviter les fuites de mémoire


Sujet :

C

  1. #1
    Membre confirmé
    Profil pro
    amateur
    Inscrit en
    Avril 2012
    Messages
    145
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : amateur
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Avril 2012
    Messages : 145
    Par défaut éviter les fuites de mémoire
    Je cherche a cataloguer les situations de fuites de mémoire, et des moyens de les éviter. Pour l'instant, les cas suivants de fuite me viennent à l'esprit:
    * un pointeur est annulé (NULL), sa cible n'est pas libérée (et elle n'est pas pointée par ailleurs)
    * dans une structure liée (arbre, liste...), un ou plusieurs noeuds sont retirés ou "coupés" et pas libérés
    * une donnée temporaire est alloué sur le tas (genre tableau dynamique) dans une fonction et pas (encore) libéré lors du return
    * un pointeur change de valeur (d'adresse), sa cible précédente n'est pas libérée
    En fait tous ces cas se recoupent, il s'agit toujours d'une cible qui n'est plus pointée/utilisée/accessible. Voyez-vous d'autres cas?

    Alors, comment éviter cela, sachant la (fameuse) faillibilité humaine? comment faites vous vous-même? Le seul cas qui me semble évitable malgré cette faillibilité est le premier: il "suffit" de toujours lier libération de mémoire et annulation de pointeur --ce qui d'ailleurs évite en même temps les pointeurs dangling (quel est le terme consacré en français? je verrais bien flottant). Des outils d'analyse sont-ils utiles? fiables? Aussi, comment fait-on pour seulement savoir qu'il y a une fuite?

    Merci,
    denis

  2. #2
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 308
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 308
    Billets dans le blog
    5
    Par défaut
    Je dirai simplement : "Joli tour d'horizon". Je ne vois pas grand chose à ajouter sauf utiliser valgrind pour avoir une idée des oublis humains de libération mémoire .

  3. #3
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par denispir Voir le message
    * une donnée temporaire est alloué sur le tas (genre tableau dynamique) dans une fonction et pas (encore) libéré lors du return
    Pourrais-tu expliquer ce cas, stp?

    Citation Envoyé par denispir Voir le message
    En fait tous ces cas se recoupent, il s'agit toujours d'une cible qui n'est plus pointée/utilisée/accessible
    A ma connaissance, c'est effectivement le seul cas possible pour une fuite mémoire : une zone a été allouée et le ou les pointeurs permettant d'accéder à cette zone sont "perdus" (ils deviennent nuls, leur durée de vie a atteint son terme, ils changent de valeur...) sans que la mémoire soit libérée avec free(). Comme il n'y a pas de garbage collector en C, la mémoire reste allouée jusqu'à la fin du programme.


    Citation Envoyé par denispir Voir le message
    Alors, comment éviter cela, sachant la (fameuse) faillibilité humaine? comment faites vous vous-même?
    Il n'y a qu'une seule solution : être exigeant et attentif en programmant. Pour vérifier son travail, il existe des outils (à ce qu'il parait.... car je n'ai encore jamais pris le temps de les essayer )

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par Bktero Voir le message
    Comme il n'y a pas de garbage collector en C, la mémoire reste allouée jusqu'à la fin du programme.
    N'est-ce pas carrément jusqu'à l'extinction/reboot de l'OS qui clean la mémoire ?
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  5. #5
    Membre confirmé
    Profil pro
    amateur
    Inscrit en
    Avril 2012
    Messages
    145
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : amateur
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Avril 2012
    Messages : 145
    Par défaut
    Citation Envoyé par Bktero Voir le message
    Pourrais-tu expliquer ce cas, stp?
    J'ai un cas tout récent: pour implanter filter, je fais ceci:
    * allouer un tableau d'indices temporaire de la taille de la structure d'origne (qui est la taille maxi du tableau résultat)
    * faire un cycle de filtrage au cours duquel je collecte les indices des éléments qui passent le filtre, et en même temps les compte
    * enfin allouer le tableau résultat à la bonne taille et copier dedans les éléments dont les indices ont été collectés
    ... et libérer le tableau d'indices ;-)

    J'ai aucune idée si c'est un bon algo, ou si c idiomatique en C, mais ça marche et je donne ça juste comme exemple.

    (Ceci présuppose un type de tableau, ou d'autre structure genre liste avec un wrapper autour, qui connaît son compte d'éléments, ou encore un tableau avec un élément bouchon genre \0.)

    Denis

  6. #6
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Cela dois dépendre de l'OS, mais dans la majorité des cas, les ressources utilisées sont libérées à la fermeture du programme.

    En effet, un programme a un espace en mémoire rien que pour lui.
    A la fin du programme on désalloue donc tout cet espace mémoire.

    Après, certaines ressources ne sont pas libérées comme les tubes ouverts par exemples.

  7. #7
    Membre confirmé
    Profil pro
    amateur
    Inscrit en
    Avril 2012
    Messages
    145
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : amateur
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Avril 2012
    Messages : 145
    Par défaut
    Citation Envoyé par Bousk Voir le message
    N'est-ce pas carrément jusqu'à l'extinction/reboot de l'OS qui clean la mémoire ?
    Je crois que l'OS libère toute la mémoire allouée à un process quand celui est terminé (normalement ou pas). A confirmer.

    Denis

  8. #8
    Membre Expert Avatar de Trademark
    Profil pro
    Inscrit en
    Février 2009
    Messages
    762
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 762
    Par défaut
    Pour les outils, il y en a un très bon et très facile à utiliser, ça te dit s'il y a des fuites mémoires et potentiellement à quelle ligne ! Il s'agit d'un utilitaire nommé Valgrind.

  9. #9
    Membre Expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Par défaut
    Salut,

    je plussoie Gerald3d et Trademark : valgrind est L'outil, il y a aussi intel inspector qui est gratuit dans le cadre d'une utilisation non commerciale.
    Remarque qu'il est impossible en général de détecter les fuites de mémoires, même les meilleurs GC doivent garder des blocs de mémoires inutilisés.

  10. #10
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par défaut
    @denispir : tu veux dire par là que tu oubliais de libérer ton tableau temporaire à la fin de ta fonction ? Si oui, alors c'est le cas que j'ai appelé "leur durée de vie a atteint son terme". Ca reste une perte de tous les pointeurs vers une zone non libérée.



    Citation Envoyé par Bousk Voir le message
    N'est-ce pas carrément jusqu'à l'extinction/reboot de l'OS qui clean la mémoire ?
    A ma connaissance, ça se passe comme dit par Neckara et denispir. Le programme possède une zone mémoire allouée par l'OS. Quand le programme se termine, l'OS peut récupérer la zone. Ca dépend peut être de l'OS et de la qualité de sa gestion de la mémoire mais je pense que les OS modernes savent quand même faire ça.

  11. #11
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 477
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 477
    Par défaut
    Hello,

    Citation Envoyé par denispir Voir le message
    Voyez-vous d'autres cas?
    Plus subtil : la ré-entrance. Si tu écris une fonction récursive qui ré-entre rarement mais qui, pour une raison donnée, ne ressors jamais, alors la totalité des variables locales et de la mémoire dynamiquement allouée (dont l'adresse est déposée dans un pointeur local) risque de jamais être libérée, sans que l'on puisse savoir si c'est normal ou pas.

    Des outils d'analyse sont-ils utiles? fiables? Aussi, comment fait-on pour seulement savoir qu'il y a une fuite?
    Ce sont les deux maîtres-mots : méthode et outils d'analyse fiables. La première permet d'éliminer en amont 90 % des fuites potentielles. Simplement en codant proprement et avec rigueur. Malgré cela, aussi expérimenté que l'on soit, il va forcément y avoir des cas qui vont nous échapper, parce que la distance qui sépare les éléments fautifs des éléments impactés dépasse « l'horizon » du programmeur. J'entends par là, la portée de ce que l'on peut voir et retenir en mémoire à un moment donné.

    Et pour cela, on ne louera jamais assez l'efficacité de valgrind. Le meilleur moyen pour s'en convaincre consiste à faire deux choses :

    • Passer valgrind sur tous les programmes que l'on a écrit jusqu'ici ;
    • Tenter ensuite d'écrire un programme qui puisse le mettre en défaut.

  12. #12
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Obsidian Voir le message
    Plus subtil : la ré-entrance. Si tu écris une fonction récursive qui ré-entre rarement mais qui, pour une raison donnée, ne ressors jamais, alors la totalité des variables locales et de la mémoire dynamiquement allouée (dont l'adresse est déposée dans un pointeur local) risque de jamais être libérée, sans que l'on puisse savoir si c'est normal ou pas.
    Je n'ai pas compris

    Qui ré-entre rarement signifie que la récursivité est peu utilisée (la condition est tout de suite vraie) ? Qui ne ressort pas = boucle infinie ?

    Pourrais-tu expliciter stp ?

  13. #13
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 477
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 477
    Par défaut
    Citation Envoyé par Bktero Voir le message
    Qui ré-entre rarement signifie que la récursivité est peu utilisée (la condition est tout de suite vraie) ? Qui ne ressort pas = boucle infinie ? Pourrais-tu expliciter stp ?
    J'entendais par là qu'il y avait très peu de rappels sur un temps donné. Imaginons par exemple que la ré-entrance n'ait lieu que sur une action particulière de l'utilisateur et que le programme est fait pour être embarqué sur un système autonome, même si l'algo est percé, le bug a peu de chances de se produire.

    Par ne « ressort pas », je voulais dire qu'une fonction récursive doit quand même atteindre sa fin pour pouvoir retourner au niveau immédiatement supérieur et, de proche en proche, au tout premier niveau, où le calcul sera effectué en entier. Si, à cause d'un bug, la fin de la fonction n'est jamais atteinte, on peut arriver à ne jamais libérer la mémoire alors que l'on est censé le faire. Et si la fonction est quand même appelée récursivement, on peut se retrouver à épuiser toute la mémoire disponible avant même d'atteindre le stack overflow.

  14. #14
    Membre confirmé
    Profil pro
    amateur
    Inscrit en
    Avril 2012
    Messages
    145
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : amateur
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Avril 2012
    Messages : 145
    Par défaut
    Citation Envoyé par Obsidian Voir le message
    Hello,
    Plus subtil : la ré-entrance. [...]

    Ce sont les deux maîtres-mots : méthode et outils d'analyse fiables. [...]

    Et pour cela, on ne louera jamais assez l'efficacité de valgrind. Le meilleur moyen pour s'en convaincre consiste à faire deux choses :
    • Passer valgrind sur tous les programmes que l'on a écrit jusqu'ici ;
    • Tenter ensuite d'écrire un programme qui puisse le mettre en défaut.
    Ouh, là là! Je sens que je vais vite devenir un fan de Valgrind ;-)
    Surtout que je programme beaucoup en récursivité...

    Denis

  15. #15
    Membre confirmé
    Profil pro
    amateur
    Inscrit en
    Avril 2012
    Messages
    145
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : amateur
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Avril 2012
    Messages : 145
    Par défaut liberation éléments collections
    Merci de toutes vos réponses.

    J'en profite pour poser une question un peu !=, mais liée au sujet: peut-on libérer d'un bloc des collections? Je tente de répondre moi-même, comme ça vous pourrez directement prodiguer des commentaires adaptés à mon dégré d'ignorance et/ou d'erreur de raisonnement ;-) Alors ma réponse est: "non".

    Ce qui m'intrigue c'est que malloc & calloc prennent en argument la taille complète, alors que free n'a qu'un pointeur qui ne peut couvrir qu'un seul élément. Bizarre, non? Comment il sait quelle est l'étendue de la zone à libérer ? (ben, il sait pas ;-)

    Le seul cas où ça pourrait marcher est celui dun tableau (1) temporaire (on est toujours dans la fonction où il est créé) (2) statique (taille constante) (3) bien déclaré en tant que tableau de cette taille-là avec [n] (pas en tant que pointeur). Dans ce cas une libération couvrirait toute la zone... mais justement dans ce cas si je pige bien le tableau est sur la pile, alors pas de libération.

    Donc, je vois pas de moyen de libérer un tableau autre qu'une stupide boucle sur les éléments.

    Ca devient plus drôle avec des structures chaînées / récursives, genre listes / arbres / réseaux. A vue de nez, à moins de mémoriser les "enfants" à chaque niveau, le plus simple serait de procéder à l'envers, des feuilles vers le tronc pour un arbre. Est-ce qu'il y a des fonctions de "libération en cascade" qui évitent de reprogrammer ça tout le temps? (et avec des erreurs)

    denis

  16. #16
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 477
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 477
    Par défaut
    Citation Envoyé par denispir Voir le message
    Ouh, là là! Je sens que je vais vite devenir un fan de Valgrind ;-)
    Surtout que je programme beaucoup en récursivité...
    Si tu compiles avec des flags stricts et que tu utilises valgrind dans les mêmes conditions, tu t'apercevras d'ailleurs qu'un certain nombre de bibliothèques systèmes souffrent des mêmes défauts.

    Ça peut être voulu (choix d'un algorithme particulier), soit connu (« ok, je ne libère pas, mais comme je sors tout de suite après, ce n'est pas grave"), soit inconnu. Dans tous les cas, valgrind permet de spécifier une liste d'exceptions pour éviter de redéclencher sans arrêt les erreurs connues. Défense de se servir de cette liste sur son propre programme. :-)

  17. #17
    Membre Expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Par défaut
    Citation Envoyé par denispir Voir le message
    Ce qui m'intrigue c'est que malloc & calloc prennent en argument la taille complète, alors que free n'a qu'un pointeur qui ne peut couvrir qu'un seul élément. Bizarre, non? Comment il sait quelle est l'étendue de la zone à libérer ? (ben, il sait pas ;-)
    malloc, calloc, free et cie ne sont que des fonctions qui te permettent de communiquer avec le gestionnaire de mémoire. Ce dernier sait tout, et lorsqu'on lui demande de libérer la mémoire d'un certain pointeur il sait combien de mémoire il lui a alloué.
    Il y a plusieurs stratégies d'allocation de mémoire. La gnu libc utilise un dérivé de dlmalloc, le kernel en utilise une autre version, tu peux toi même te créer tes versions de gestion de mémoire ... http://en.wikipedia.org/wiki/Malloc#Implementations

    EDIT: Pour info, valgrind remplace les implémentations de malloc et cie pour détecter les fuites de mémoire ... encore un autre gestionnaire

    Citation Envoyé par denispir Voir le message
    Le seul cas où ça pourrait marcher est celui dun tableau (1) temporaire (on est toujours dans la fonction où il est créé) (2) statique (taille constante) (3) bien déclaré en tant que tableau de cette taille-là avec [n] (pas en tant que pointeur). Dans ce cas une libération couvrirait toute la zone... mais justement dans ce cas si je pige bien le tableau est sur la pile, alors pas de libération.
    Donc, je vois pas de moyen de libérer un tableau autre qu'une stupide boucle sur les éléments.
    En entrée de fonction, on alloue sur la pile tout ce qui faut comme place pour y stocker les variables locale. Tu peux encore l'étendre avec un alloca (=un malloc sur le stack).
    En sortie de fonction, on remet la pile comme on l'a trouvée (ou presque) et toutes les variables locales (y compris celle que tu as allouées manuellement) seront automatiquement libérées.
    À moins de tuner ton système, la place sur la pile est chère car relativement rare.

    Si tu alloues un espace avec 1 malloc ou 1 calloc, alors il te suffira de 1 free pour libérer tout l'espace.
    Si tu as un tableau multidimensionnel, tu feras plusieurs malloc et par conséquent plusieurs free (généralement dans une boucle).

    Citation Envoyé par denispir Voir le message
    Ca devient plus drôle avec des structures chaînées / récursives, genre listes / arbres / réseaux. A vue de nez, à moins de mémoriser les "enfants" à chaque niveau, le plus simple serait de procéder à l'envers, des feuilles vers le tronc pour un arbre. Est-ce qu'il y a des fonctions de "libération en cascade" qui évitent de reprogrammer ça tout le temps? (et avec des erreurs)

    denis
    Je ne sais pas si je comprends bien ce que tu veux, mais si tu implémentes par exemple un arbre binaire avec un tableau (le noeud d'indice i a pour fils gauche 2i et pour fils droit 2i+1, la racine a pour indice 1) que tu as alloué ce tableau avec un malloc alors un free suffira.
    Si tu as construit une sdd récursive en faisant plusieurs allocations alors il te faudra plusieurs free pour tout libérer.

  18. #18
    Membre confirmé
    Profil pro
    amateur
    Inscrit en
    Avril 2012
    Messages
    145
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : amateur
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Avril 2012
    Messages : 145
    Par défaut
    Citation Envoyé par kwariz Voir le message
    malloc, calloc, free et cie ne sont que des fonctions qui te permettent de communiquer avec le gestionnaire de mémoire. Ce dernier sait tout, et lorsqu'on lui demande de libérer la mémoire d'un certain pointeur il sait combien de mémoire il lui a alloué.
    Il y a plusieurs stratégies d'allocation de mémoire. La gnu libc utilise un dérivé de dlmalloc, le kernel en utilise une autre version, tu peux toi même te créer tes versions de gestion de mémoire ... http://en.wikipedia.org/wiki/Malloc#Implementations

    EDIT: Pour info, valgrind remplace les implémentations de malloc et cie pour détecter les fuites de mémoire ... encore un autre gestionnaire

    En entrée de fonction, on alloue sur la pile tout ce qui faut comme place pour y stocker les variables locale. Tu peux encore l'étendre avec un alloca (=un malloc sur le stack).
    En sortie de fonction, on remet la pile comme on l'a trouvée (ou presque) et toutes les variables locales (y compris celle que tu as allouées manuellement) seront automatiquement libérées.
    À moins de tuner ton système, la place sur la pile est chère car relativement rare.

    Si tu alloues un espace avec 1 malloc ou 1 calloc, alors il te suffira de 1 free pour libérer tout l'espace.
    Si tu as un tableau multidimensionnel, tu feras plusieurs malloc et par conséquent plusieurs free (généralement dans une boucle).
    D'accord. Donc, si je fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
       int * p = malloc(333 * sizeof(int)) ;
       // ...
       free (p) ; p = NULL ;
    à la fin j'ai bien l'espace des 333 entiers libéré? Je n'ai pas besoin de faire une boucle sur l'espace mémoire pour les libérer un par un? J'ai besoin d'être sûr de ça, pour plus y penser ;-). (Un point embêtant, c'est qu'il n'y pas de feedback qui dise si c'est bien libéré, et encore moins combien d'espace.)

    Denis

  19. #19
    Membre Expert Avatar de Trademark
    Profil pro
    Inscrit en
    Février 2009
    Messages
    762
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 762
    Par défaut
    Oui comme ça c'est bon.

    Si tu avais fait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int **p = malloc(100*sizeof(int));
    int i;
    for(i =0; i < 100; ++i)
      p[i] = malloc(100*sizeof(int));
    Alors tu devrais faire une boucle pour libérer le tableau comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int i;
    for(i=0; i < 100; ++i)
     free(p[i]);
    free(p);

  20. #20
    Membre Expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Par défaut
    Salut,

    En fait tu passes une taille en octet à malloc, un bloc de mémoire contigu de taille au moins égale à la taille demandée est alloué et malloc te renvoie l'adresse du début du bloc.
    C'est pourquoi quand tu fais un realloc, l'adresse mémoire du premier élément peut ne pas changer. Par exemple pour ton malloc(333 * sizeof(int)), en supposant que ton int fasse 4 octets, renvoie un pointeur sur une zone mémoire de 1332 octets, si ça se trouve le gestionnaire aura en fait réservé (pour des raison de perf) 4096 octets. Si tu augmentes la taille par un realloc, rien ne se passe tant que tu ne dépasses pas 4096 octets (1024 int). En revanche, si l'adresse change, il est clair qu'il y a eu copie de contenu.

    free ne renvoie rien en effet, car soit la mémoire est libérée correctement et entièrement (dans ce cas RAS) soit il y a un très très gros problème comme un bug dans le gestionnaire de mémoire . free ne sert pas à réduire la mémoire allouée (c'est le boulot de realloc) mais de la libérer en intégralité.

    La règle est si tu fais 1 malloc tu dois faire un 1 free (pas plus pas moins). Attention certaines fonctions font des malloc aussi, par exemple strdup. Si tu dupliques une chaine avec strdup il faudra aussi penser à libérer cet espace.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Détecter les fuites de mémoire sous Windows
    Par Nadawoo dans le forum Débuter
    Réponses: 1
    Dernier message: 25/11/2010, 00h26
  2. Outils pour detecter les fuite de mémoire
    Par sese12345 dans le forum Windows Mobile
    Réponses: 2
    Dernier message: 31/03/2010, 10h10
  3. [débutant] comment éviter les fuites de mémoire ?
    Par dahtah dans le forum Général Java
    Réponses: 6
    Dernier message: 13/03/2007, 17h40
  4. Comme intercepter les fuites de mémoire sous VS?
    Par Gabrielly dans le forum Visual C++
    Réponses: 4
    Dernier message: 18/09/2006, 20h57
  5. Réponses: 8
    Dernier message: 17/10/2002, 12h52

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