OVH Cloud OVH Cloud

Utilité DLL C++

102 réponses
Avatar
Korchkidu
Bonjour,

A partir de quand estimez vous que faire une DLL plutot qu'un LIB soit
int=E9ressant. En effet, utiliser des DLL fait des programmes plus
petits (entre autres) mais induit d'enormes contraintes au niveau de la
programmation. Donc d'apres moi, faire une DLL pour une bibliotheque de
petite taille n'est pas forcement une bonne idee...

Merci pour vos commentaires.
K=2E

10 réponses

1 2 3 4 5
Avatar
Alain Gaillard

En es-tu certain ?


Il peut l'être sous Windows.


Ce n'est pas ce que j'ai compris jusqu'ici,
et ça ne correspond pas au nom. Au moins sous Windows


Mon bon James, tu manques un peu d'expérience dans le domaine ;)
(pardonne moi mais je n'ai pas pu m'en empêcher:) )
Sous Windows les dll ne sont chargées qu'une fois en mémoire, ce qui est
heureux car sinon tout le système, qui est constitué uniquement de dll
serait chargé par chaque application. kernel32.dll, user32.dll. Tu
imagines ?

Le mécanisme de gestion de mémoire virtuelle est assez particulier. En
quelques mots disons que toute application se voit attribuer les 4 Go
adressables, mais toute cette zone est une zone de mémoire virtuelle,
pas physique évidemment. Les 2 go de mémoire basse sont à son usage.
Dans les 2 Go de mémoire haute sont installée les tables de saut vers
les dll utilisées par l'application, comme par exemple kernel32.dll,
user32.dll, madll.dll. Je parle bien ici de mémoire virtuelle.

Quand une appli appelle une fonction de dll, elle saute quelque part
dans ces deux Go de mémoire haute puis de là saute dans la mémoire
*physique* où est effectivement chargée la dll. Et cette dll ne réside
qu'une fois en mémoire physique.

--
Alain

Avatar
Vincent Burel
"Alain Gaillard" wrote in message
news:45013aa5$0$25908$
Le mécanisme de gestion de mémoire virtuelle est assez particulier. En
quelques mots disons que toute application se voit attribuer les 4 Go
adressables, mais toute cette zone est une zone de mémoire virtuelle,
pas physique évidemment. Les 2 go de mémoire basse sont à son usage.
Dans les 2 Go de mémoire haute sont installée les tables de saut vers
les dll utilisées par l'application, comme par exemple kernel32.dll,
user32.dll, madll.dll. Je parle bien ici de mémoire virtuelle.

Quand une appli appelle une fonction de dll, elle saute quelque part
dans ces deux Go de mémoire haute puis de là saute dans la mémoire
*physique* où est effectivement chargée la dll. Et cette dll ne réside
qu'une fois en mémoire physique.


Pour un process donné oui... Pour deux process utilisant la meme DLL, je ne
suis pas certain que cette DLL ne soit pas physiquement chargé 2 fois...

VB

Avatar
Jean-Claude BELLAMY
Dans le message :450142a2$0$27367$,
Vincent Burel a pris la peine d'écrire ce
qui suit :
"Alain Gaillard" wrote in message
[...]
Quand une appli appelle une fonction de dll, elle saute quelque part
dans ces deux Go de mémoire haute puis de là saute dans la mémoire
*physique* où est effectivement chargée la dll. Et cette dll ne
réside qu'une fois en mémoire physique.


Pour un process donné oui... Pour deux process utilisant la meme DLL,
je ne suis pas certain que cette DLL ne soit pas physiquement chargé
2 fois...


Exact !!!

Ce qui retire d'ailleurs pas mal d'intérêt aux DLL en ce qui concerne
l'encombrement mémoire.
Cela date du monde 16 bits, la "mono-résidence" en mémoire de DLL.
Le passage en 32 bits a modifié cette gestion.

--
May the Force be with You!
La Connaissance s'accroît quand on la partage
----------------------------------------------------------
Jean-Claude BELLAMY [MVP]
http://www.bellamyjc.org ou http://jc.bellamy.free.fr


Avatar
Alain Gaillard


Exact !!!


FAUX!!!


Ce qui retire d'ailleurs pas mal d'intérêt aux DLL en ce qui concerne
l'encombrement mémoire.



Regardez par exemple les dépendances du Notepad. Il utilise
Kernel32.dll, gdi32.dll, user32.dll, comctl32.dll, shell32.dll,
msvcrt.dll, pour ne citer que ça et tout son processus n'occupe que 600k
environ. Si toutes ces dll étaient chargées en mémoire au lancement du
notepad, ça ferait beaucoup plus.

Vous imaginez un peu le notepad chargeant le noyau de windows ??
(kernel32.dll) Une application qui chargeait le noyau de son OS c'est
quand même le monde à l'envers. Assez psychédélique ;-) :-)

La MSDN est tout à fait claire au sujet des dll:

"DLLs provide a way to modularize applications so that functionality can
be updated and reused more easily. They also help reduce memory overhead
when several applications use the same functionality at the same time,
because although each application gets its own copy of the data, they
can share the code"

Cela date du monde 16 bits, la "mono-résidence" en mémoire de DLL.
Le passage en 32 bits a modifié cette gestion.


Dans tes rêves...

--
Alain

Avatar
Vincent Burel
"Alain Gaillard" wrote in message
news:450156cb$0$5106$

"DLLs provide a way to modularize applications so that functionality can
be updated and reused more easily. They also help reduce memory overhead
when several applications use the same functionality at the same time,
because although each application gets its own copy of the data, they
can share the code"


Ha ouai, chaque process à ses donnée propres de ses DLL, ca devrait suffire
effectivement...

Avatar
Arnold McDonald \(AMcD\)
Jean-Claude BELLAMY wrote:

Exact !!!

Ce qui retire d'ailleurs pas mal d'intérêt aux DLL en ce qui concerne
l'encombrement mémoire.


N'importe quoi...

Prends un debugguer et scrute quelques applis. Ne confond pas chargé et
mappé, ne confonds pas en mémoire et sur disque. Et ne confond pas données
et code...

Eh ! Les vacances sont finies, faut se reconcentrer man :-).

--
Arnold McDonald (AMcD)

http://arnold.mcdonald.free.fr/

Avatar
Jean-Claude BELLAMY
Dans le message :45017658$0$6978$,
Arnold McDonald (AMcD) a pris la peine d'écrire ce
qui suit :
Jean-Claude BELLAMY wrote:
Une conceté !

[...]
Prends un debugguer et scrute quelques applis. Ne confond pas chargé
et mappé, ne confonds pas en mémoire et sur disque. Et ne confond pas
données et code...

Eh ! Les vacances sont finies, faut se reconcentrer man :-).


Justement, je n'ai pas encore pris de vacances ! (il faut je j'attende
dimanche 17)

Oui, j'ai répondu trop vite et j'ai dit une conceté !
(d'ailleurs au moment où j'ai posté j'avais un pressentiment!)
Mais je n'ai jamais confondu mémoire et sur disque, ni données et code,
quand même !

Je m'étais rappelé l'article du MSDN "How To Build and Service Isolated
Applications and Side-by-Side Assemblies for Windows XP", à propos des
applications "autonomes" sous cet OS. J'ai retrouvé l'URL :
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwxp/html/sidexsidewinxp.asp

Je venais par ailleurs de recompiler un contrôle ActiveX alors qu'il était
en cours d'utilisation par une autre appli, et tout çà sans aucune
injurebox, ce qui m'a évoqué cette phrase de l'article cité plus haut
(dans le paragraphe intitulé "Step two: Design and author DLLs so that
multiple DLLs may run safely"):
"DLLs need to be authored so that multiple versions can run
at the same time in a process without impacting each other"

Donc s'il peut y avoir simultanément plusieurs versions de la même DLL,
c'est que forcément ces versions occupent des emplacements mémoire
différents.
Si bien que j'ai extrapolé un peu trop rapidement et me suis mélangé les
octets...

Désolé ..


--
May the Force be with You!
La Connaissance s'accroît quand on la partage
----------------------------------------------------------
Jean-Claude BELLAMY [MVP]
http://www.bellamyjc.org ou http://jc.bellamy.free.fr

Avatar
kanze
Rémy wrote:
"kanze" a écrit dans le message de news:

Rémy wrote:

Nous utilisons des DLL (en fait des .so) pour les modules
communs d'applications composées de plusieurs (dizaines) de
processus. Ca n'apporte rien fonctionnellement par rapport
à l'édition de liens statique, mais ça économise
considérablement la mémoire car le code n'est présent
qu'une fois en mémoire.


En es-tu certain ? Ce n'est pas ce que j'ai compris
jusqu'ici, et ça ne correspond pas au nom. Au moins sous
Windows : je sais que la taille était bien la motivation
principale des « shared objects » sous Sun OS, dans le
temps, mais je croyais qu'il s'agissait principalement de la
taille sur disque (à une époque où la taille des disques se
mesurait en Mo, et non Go, et que la taille de la
bibliothèque graphique était bien plusieurs Mo).


Oui (en tout cas sur les OS sur lesquels je travaille
habituellement : Sun OS, HP-UX, Tru 64 et Linux.


En effet. J'ai jeté un coup d'oeil à l'assembleur généré pour
malloc, pour Linux, et ils ont fait ce qu'il faut pour que ça
marche. (Je n'ai pas vérifié en détail que les exécutables
partagent le code, mais générer l'assembleur comme ils l'ont
fait n'a pas de sens autrement.)

J'aurais cru qu'avec l'augmentation des tailles mémoire, qu'on
aurait préféré l'optimisation vitesse -- parce que l'interface
PIC qu'ils utilisent a bien un coup non negligeable en temps
d'exécution. Que tu paies à chaque appel de fonction, et non
seulement lors du chargement. (Pour une fonction simple
comme :
int
f()
{
static int i = 0 ;
return i ++ ;
}
le temps d'exécution pourrait prèsque doublé. L'effet quand la
fonction n'utilise pas de variables statiques, en revanche, est
bien moindre.)

C'est possible que l'image en mémoire soit partagé ; c'est
même l'idée derrière le PIC (« position independant code »,
mais ça augmente aussi la vitesse de chargement de façon
notable, même si l'image n'est pas partagé).


Oui, aussi.

Mais ça suppose aussi que l'objet
partagé ne réfère jamais à rien dans le main,


Effectivement, il vaut mieux que le .so ne réfère rien dans le main...


Et cependant, pour un plug-in, ça peut être intéressant.

Mais pour des composants communs, il vaut mieux ne pas
dépendre de l'utilisateur. Seulement d'autres composants
communs et encore, en évitant les dépendances circulaires...

et que s'il réfère à quelque chose dans un autre objet
partagé (libc, par exemple), que cet autre objet soit lié à
la même adresse dans tous les exécutables (rélative à
l'adresse de mon objet partagé, au moins).


Ma foi, je pense que c'est le boulot de l'édition de lien dynamique
d'assurer que ça marche.


Oui, mais à quel coût. Il y introduit un niveau d'indirection
supplémentaire à chaque appel. Voire deux. En fait, l'édition de
liens ne se fait que partiellement dans dlopen. Une bonne partie
se réfait, dynamiquement, à chaque appel.

Je ne sais pas s'il est nécessaire que les objets soient à la
même adresse dans tous les exécutables ?

Par ailleurs, ça permet de livrer les corrections des
modules communs sans que le programme les utilisant n'ait à
être relinké.


C'est justement le gros problème. L'utilisateur finit très
vite avec un melange de versions incompatibles.


Il y a un travail sérieux pour s'assurer de la compatibilité
ascendante. Il n'y a pas de "mélange" de version car (dans
notre cas) une nouvelle version remplace la précédente (les
composants communs sont installés une seule fois sur la
machine et pas avec chaque exécutable).


Je suppose que ton équipe est la seule qui s'en servent, et
qu'elle gère bien le code, et y a pensé. Dans notre cas, il y
plusieurs équipes, et la contrôle de ce qui va dans chaque
version est assez limitée.

C'est une contrainte supplémentaire sur l'évolution.

Ici, ils avaient fait à peu près pareil, avec l'idée
qu'effectivement, la plupart des bibliothèques servaient à
plusieurs exécutables. Seulement, juste au moment où j'y
suis arrivé, on a eu des crashs en production parce que
$LD_LIBRARY_PATH ne désignait pas le chemin vers la bonne
version de la bibliothèque


Problème effectivement si on installe plusieurs versions sur
la même machine


Disons qu'en général, si chaque exécutable est livrée avec tous
les objets partagés qui lui servent, il n'y a vraiment aucun
gain. Et dès qu'on ne prend pas en compte les problèmes de
compatibilité ascendante, c'est ce qu'il va falloir.

Ensuite, c'est une décision pragmatique qui s'impose. Si
l'utilisation des objets partagés fait réelement une différence
importante, que la contrainte de la compatibilité ascendante
ne pose pas de grands problèmes (ou qu'elle est présente de
toute façon, pour d'autres raisons), et que tu maîtrises un peu
les environements où vont tournés les exécutables, l'utilisation
des objets partagés peut se justifier.

-- un peu de récherche a montré
qu'en fait, les versions des exécutables (livrées par des
équipes différentes) étaient telles que chaque exécutable avait
besoin d'une version différente des bibliothèques.


Si chacun fait évoluer les composants communs de façon
incompatible... Eh bien, ils ne sont plus communs...


Le problème, c'est qu'on fasse évoluer une fonctionnement de
façon qu'il ne soit plus compatible avec l'ancienne version. Du
coup, les applications qui n'ont pas été modifiées ne
fonctionnent qu'avec les anciennes versions.

Il faut ajouter que les binaires des différentes versions du
compilateur ne sont pas compatible non plus, au moins en ce qui
concerne le C++. Selon les équipes, on utilise trois différentes
versions de Sun CC (dont la très ancienne 4.2), plus g++. Et
qu'il faudrait un objet partagé différent pour chaque version.

Je pense que ce n'est faisable qu'avec une organisation
adaptée. Dans notre cas, il y a une équipe chargée de toutes
les livraisons qui réceptionne les sources de tous les
produits (communs ou pas), recompile tout sur une machine
dédiée et génère les produits à installer.


C'est sûr qu'avec une bonne organisation, on a plus de chances à
ce que ça marche qu'avec une mauvaise:-).

Les bibliothèques étaient donc présentes autant de fois
qu'il y avait d'exécutables, dans de versions différentes.
Pas de gain de place, donc, et une risque réele de chopper
la mauvaise version.


C'est comme beaucoup d'outils, si on s'en sert mal (ou sans
les contrôler), on peut faire de gros dégâts ;-)


Tout à fait. Et chaque fois, il s'agit de comparer ce que ça
peut apporter par rapport aux prix que ça impose. Il y a
certainement des cas où le gain de place mémoire est à prendre
en compte.

Une question supplémentaire : est-ce que quelqu'un sache si ça
marche pareil sous Windows ? Je ne vois pas d'option pour
générer du PIC. Je doute donc que c'est possible, mais je ne
connais pas la plate-forme assez bien pour être sûr.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34



Avatar
kanze
Alain Gaillard wrote:

En es-tu certain ?


Il peut l'être sous Windows.

Ce n'est pas ce que j'ai compris jusqu'ici, et ça ne
correspond pas au nom. Au moins sous Windows


Mon bon James, tu manques un peu d'expérience dans le domaine
;) (pardonne moi mais je n'ai pas pu m'en empêcher:) )

Sous Windows les dll ne sont chargées qu'une fois en mémoire,
ce qui est heureux car sinon tout le système, qui est
constitué uniquement de dll serait chargé par chaque
application. kernel32.dll, user32.dll. Tu imagines ?


J'aurais imaginé que ces DLL ne contient que le mapping de l'API
C aux véritables appels systèmes (qui n'était pas des call dans
le temps, parce qu'il fallait passer en mode superuser, masquer
les interruptions, etc.). Mais de toute façon, le système
lui-même est un cas à part, parce qu'en aucun cas il ne faut le
mapper dans l'espace utilisateur.

Le mécanisme de gestion de mémoire virtuelle est assez
particulier. En quelques mots disons que toute application se
voit attribuer les 4 Go adressables, mais toute cette zone est
une zone de mémoire virtuelle, pas physique évidemment. Les 2
go de mémoire basse sont à son usage. Dans les 2 Go de
mémoire haute sont installée les tables de saut vers les dll
utilisées par l'application, comme par exemple kernel32.dll,
user32.dll, madll.dll. Je parle bien ici de mémoire virtuelle.


Il lui faut 2 Go pour ça ?

Quand une appli appelle une fonction de dll, elle saute
quelque part dans ces deux Go de mémoire haute puis de là
saute dans la mémoire *physique* où est effectivement chargée
la dll. Et cette dll ne réside qu'une fois en mémoire
physique.


Pour les sauts dans le code, je comprends bien comment ça
marche, bien que j'ai du mal à croire que tout le monde soit
d'accord pour le prix de l'indirection supplémentaire. Et pour
les sauts à l'intérieur d'une DLL, il n'y a évidemment aucun
problème, parce que les sauts sur un Intel (sauf pour les
adresses FAR, mais ni Windows ni Linux ne les supporte) sont
rélatifs. Le problème se pose, en revanche, dès qu'une fonction
ait des données statiques -- il faut tout un cirque pour s'y
accéder.

Je viens de vérifier et sous Linux et sous Solaris, et quand tu
donnes l'option -fpie (g++) ou -PIC (Sun CC), le compilateur
génère le code supplémentaire nécessaire. Ce qui va rallentir
considérablement une fonction très simple qui se sert d'une
variable statique, mais de telles fonctions ne font certainement
pas la majorité de beaucoup d'applications. (En revanche, ça
doit avoir un effet notable sur des fonctions dans <ctype.h>.)
Je ne trouve pas d'option pareil dans VC++ (mais j'avoue que je
n'ai fait que « cl /help » pour régarder -- et peut-être ils
l'ont appelé quelque chose d'autre, et que je ne reconnais pas
la description.)

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
Arnold McDonald \(AMcD\)
Jean-Claude BELLAMY wrote:

Justement, je n'ai pas encore pris de vacances ! (il faut je j'attende
dimanche 17)


Patience, plus que 9 jours !

Oui, j'ai répondu trop vite et j'ai dit une conceté !
(d'ailleurs au moment où j'ai posté j'avais un pressentiment!)


T'inquiète, ça arrive à tout le monde. J'ai été simplement surpris de ta
part.

Mais je n'ai jamais confondu mémoire et sur disque, ni données et
code, quand même !


C'était une extrapolation. Je voulais signifier que les données étaient
dupliquées, pas le code. Pareil pour le mapping et le chargement (disque et
mémoire).

Si bien que j'ai extrapolé un peu trop rapidement et me suis mélangé
les octets...

Désolé ..


Pas de problème, la prochaine fois, ce sera toi qui me reprendra :-).

--
Arnold McDonald (AMcD)

http://arnold.mcdonald.free.fr/

1 2 3 4 5