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

Windows Discussion :

Nécessité/utilité de FreeLibrary()


Sujet :

Windows

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2010
    Messages
    44
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Novembre 2010
    Messages : 44
    Points : 59
    Points
    59
    Par défaut Nécessité/utilité de FreeLibrary()
    Bonjour à tous,

    Je voulais savoir/avoir des éclaircissements quant à la nécessité de FreeLibrary() (après un LoadLibrary()).
    Je sais (si je me trompe pas), en gros, que lorsqu'on load une dll avec LoadLibrary(), c'est en fait un "pseudo" pointeur qui est copié dans l'espace d'adressage du programme appellant, et le compteur de référence à cette dll est incrémenté. En appellant FreeLibrary(), le compteur de référence est diminué, s'il atteint zéro, la dll est déchargée de la mémoire.
    C'est justement là que je me pose la question de l'utilité de FreeLibrary :
    - si l'on charge une dll dite 'système', on est presque sur que cette dll restera chargé toute l'execution de windows, le compteur de référence ne sera jamais à zéro, d'où ma question sur l'utilité de FreeLibrary() dans ce cas
    - si l'on charge une dll perso par exemple, le fait que le programme est détruit à la fin de son execution détruit aussi la mémoire allouée au programme (donc la mémoire alloué à la dll) non ? ou la dll est chargé en dehors et il n'y a réellement dans ce cas aussi que le pointeur qui est copié dans l'adressage mémoire du programme appellant?

    Mon raisonnement est forcément erroné quelque part, FreeLibrary a forcément une utilité dans un certain contexte, mais je vois pas du tout, peut-être avec vos éclaircissements ...

  2. #2
    Rédacteur
    Avatar de Neitsa
    Homme Profil pro
    Chercheur sécurité informatique
    Inscrit en
    Octobre 2003
    Messages
    1 041
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chercheur sécurité informatique

    Informations forums :
    Inscription : Octobre 2003
    Messages : 1 041
    Points : 1 956
    Points
    1 956
    Par défaut
    Bonjour,

    Citation Envoyé par hh-cx Voir le message
    Je sais (si je me trompe pas), en gros, que lorsqu'on load une dll avec LoadLibrary(), c'est en fait un "pseudo" pointeur qui est copié dans l'espace d'adressage du programme appellant, et le compteur de référence à cette dll est incrémenté. En appellant FreeLibrary(), le compteur de référence est diminué, s'il atteint zéro, la dll est déchargée de la mémoire.
    C'est exact. (Concrètement le HMODULE retourné est l'adresse de base du module dans l'espace d'adressage du processus.)

    - si l'on charge une dll dite 'système', on est presque sur que cette dll restera chargé toute l'execution de windows, le compteur de référence ne sera jamais à zéro, d'où ma question sur l'utilité de FreeLibrary() dans ce cas
    En fait l'assertion est valide uniquement pour deux DLLs: ntdll et kernel32. Le processus - et son thread primaire - ont besoin de ces deux DLLs pour s'initialiser (n.b: possible que ce soit aussi le cas avec user32 si le programme est un programme avec GUI).

    Ces deux DLLs ne peuvent pas être déchargées du processus. Dans la liste interne où se trouve le compteur de référence des DLLs, elles ont un drapeaux spécial qui interdit leur déchargement. Du coup, le compteur n'a aucun effet.

    - si l'on charge une dll perso par exemple, le fait que le programme est détruit à la fin de son execution détruit aussi la mémoire allouée au programme (donc la mémoire alloué à la dll) non ?
    Oui en un sens. La mémoire allouée pour la DLL disparait aussi avec la fin du processus. Mais c'est un peu plus complexe dans certains cas (voir réponse suivante).

    ou la dll est chargé en dehors et il n'y a réellement dans ce cas aussi que le pointeur qui est copié dans l'adressage mémoire du programme appellant?
    En fait si une DLL est mappée pour plusieurs processus (cas typique des DLLs système) alors il y un un seul mapping en mémoire physique et toutes les pages virtuelles pointent vers la page physique.

    Exemple: deux processus 'A' et 'B' mappent tous les deux la DLL 'D'. Plutôt que de mapper la DLL dans les deux espaces d'adressage des processus A et B (ce qui doublerait la consommation de mémoire en ce qui concerne la DLL), la DLL est mappé une fois en mémoire système et les pages virtuelles de D dans A et B pointent vers une seule et même 'instance' de D.

    On voit deux DLLs 'D' mais en réalité il n'y en a qu'une seule. Toutefois, sur cette DLL, le système applique un mécanisme dit de "copy-on-write" (c.f. le KB à ce propos: http://support.microsoft.com/kb/103858, ou encore: http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx).

    Si jamais la DLL 'D' venait à être différente entre 'A' et 'B' (concrètement: si une page venait à être écrite sur la DLL 'D' dans un des processus) alors le système mappe dans l'espace du processus ayant fait l'écriture une page qui ne sera disponible que pour lui. Ce mécanisme s'applique même dans le cas où des fixups sont obligatoires (cas de l'ASLR).

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2010
    Messages
    44
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Novembre 2010
    Messages : 44
    Points : 59
    Points
    59
    Par défaut
    Tout d'abord, merci de votre réponse Neitsa, vous avez beaucoup éclaircit les choses et apporter de nouvelles informations.

    Si j'ai bien tout compris de votre post, si j'ai un programme qui charge une dll écrite que pour le programme appellant, il est inutile d'utiliser FreeLibrary(), l'espace mémoire alloué va être libéré en même temps que la fin d'execution du programme.
    Pour les dll système (hormis kernel32, ntdll et user32 qui ne peuvent être libérées), elles sont certainement (mais pas forcément) mappées par d'autres applications, dans ce cas, le FreeLibrary() décrémentera le compteur de référence et l'usage de cette fonction a un donc intérêt.

    Merci de toutes ses informations.

  4. #4
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 942
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 942
    Points : 5 654
    Points
    5 654
    Par défaut
    Jao,

    À part comprendre comment ça marche, je ne vois pas pourquoi tu te poses la question.

    Tu as une instruction de chargement, et une de libération qui lui correspond, pourquoi ne pas les utiliser correctement ?

    Tu cherches à t'économiser une ligne de code de temps en temps (probablement sur des centaines ou milliers [...]) ?
    Si les cons volaient, il ferait nuit à midi.

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2010
    Messages
    44
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Novembre 2010
    Messages : 44
    Points : 59
    Points
    59
    Par défaut
    12 (condition if) + 12x1ligne (freelibrary())x 3 (verification après 3 fonctions différentes) OU 3 appels vers une fonction de 12 conditions + 1x12 ligne FreeLibrary().

    C'est pas tellement le nombre de ligne qui me dérange, mais le nombre d'instructions à executer à la sortie du programme (sortie correcte ou arrêt prématuré).

    C'est 12 dll (développer que pour l'application uniquement, des .lib destiné à unix à la base devenu .dll, le portage de l'application étant notre tache) à mapper. 12 condition, parce qu'un FreeLibrary() sur un HMODULE inexistant fait planter.

    Et la structure du programme initialement (4 fonction: _init, _grant, _proceed, _cleanshutdown) m'ont forcé à placer le mapping des dll dans _init, et je dois donc décharger les dll (ou dumoins placer la fonction pour dé-mapper les dll) si y'a un problème après les 3 premières fonctions si l'une d'elle venait à échouer ... je trouve que ca fait beaucoup au final d'instructions si les DLL vont être détruite à la fin du programme exactement comme si je les avais FreeLibrary(), surtout que l'application risque d'être ré-executé directement après son arrêt, dans un environnement interne (sur les postes en interne).

    Voilà pourquoi je me suis questionné sur le fonctionnement et l'utilité de FreeLibrary dans le cas de DLL personnelles à l'application appellante et sur le fonctionnement en général, pour éviter les fameuses 12 + 1x12 appellée 3 fois (comme détaillé plus haut )

    Ca reste propre non?

  6. #6
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    C'est une "fuite propre", en fait: Une fuite qui est résolue à la fin du programme et n'augmente pas en taille durant l'exécution.

    Mais ça reste une fuite.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2010
    Messages
    44
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Novembre 2010
    Messages : 44
    Points : 59
    Points
    59
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Une fuite qui est résolue à la fin du programme. Mais ça reste une fuite.
    Je suis pas d'accord. tu le dis toi même, il n'y a pas d'accroissement incontrolé d'usage de mémoire durant l'execution. Ou voit-tu donc la fuite de mémoire? Et la fin du programme, c'est la dé-allocation de la mémoire attribué au programme (et donc aux DLL mappée), et non pas l'arrêt d'une croissante allocation de mémoire non désirée ou non controlée. (si l'on prend comme définition de fuite justement l'augmentation d'usage incontrolée et non désirée de la mémoire par une instruction/processus/programme).

  8. #8
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 367
    Points
    50 367
    Par défaut
    Ce n'est pas une fuite au sens strict du terme, il n'y a effectivement pas accroissement de la mémoire au fur et à mesure que le temps passe.

    Ceci dit, ce que l'on prend explicitement, une programmation propre demande qu'on le rende explicitement même si cela va être rendu implicitement par le système dans 1/2 seconde lors de l'arrêt du programme. C'est plus propre et cela participe à la maitrise de l'utilisation et de la restitution des ressources.

    Imagine que tu copies/colles ce bout de code dans un service ou bien dans une boucle de 10000 itération, si la libération explicite n'y est pas initialement, tu vas l'oublier et tu risques de le payer.
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2010
    Messages
    44
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Novembre 2010
    Messages : 44
    Points : 59
    Points
    59
    Par défaut
    ram-0000,

    Je suis d'accord, il faut coder propre, il n'y a pas à en discuter.
    La, il était question d'appeller à l'arret du programme (arret correct ou sortie en erreur) une fonction ou un couple d'instruction faisant une douzaine de condition et si valide un appel par condition de FreeLibrary pour des DLL chargés et utilisées uniquement par le programme appellant, et donc de l'intérêt d'un FreeLibrary si l'on sait à coup sur (et c'est le cas) que la DLL n'aura pas de compteur de référence dépassant 1 et donc déchargée automatiquement à l'arrêt du programme appellant. Je voulais m'assurer que c'est le comportement du système pour ce cas là, c'est fais grace à vos réponses et vos éclaircissements.

    Je jure que je ne remet aucunement en cause le fait de coder propre. Il est sur que pour toutes les autres DLL que j'ai/je vais devoir mappé (le portage de l'application est en cours et je n'ai pas encore de visu complet sur le travail à accomplir), je vais faire proprement les choses.

    Ton commentaire par contre m'a poussé à une interrogation : si dans le cas d'un service on mappe une dll 'perso', le comportement est il le même (dé-allocation système de la mémoire alloué au dll ou pas) ? j'aurai tendance à penser que c'est le même, mais ta remarque me pousse au doute.
    Et puis je percute pas trop l'exemple des boucles, tu peux m'expliquer plus s'il te plait? je n'arrive pas à me faire un exemple d'une probable fuite dans mon cas en utilisant une boucle ...

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

Discussions similaires

  1. Utilité d'un pointeur vers une fonction ?
    Par Nasky dans le forum C
    Réponses: 10
    Dernier message: 20/03/2010, 19h54
  2. [J2EE] Utilité de la J2EE de SUN ?
    Par PeteMitchell dans le forum Java EE
    Réponses: 4
    Dernier message: 14/05/2004, 10h29
  3. [LG]Utilité du type enuméré ?
    Par tarbala dans le forum Langage
    Réponses: 2
    Dernier message: 10/12/2003, 16h20
  4. Le BIOS et son utilité
    Par le mage tophinus dans le forum Assembleur
    Réponses: 75
    Dernier message: 21/11/2003, 15h37
  5. utilité du binaire et hexadecimaux?
    Par souris78 dans le forum C
    Réponses: 9
    Dernier message: 01/07/2003, 15h08

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