514 votes

Quand utiliser des bibliothèques dynamiques ou statiques

Lors de la création d'une bibliothèque de classes en C++, vous pouvez choisir entre une bibliothèque dynamique ( .dll , .so ) et statique ( .lib , .a ). Quelle est la différence entre elles et quand convient-il de les utiliser ?

2 votes

Il convient de noter qu'il existe également un contrôle appelé "Bibliothèque d'importation". stackoverflow.com/questions/3573475/

361voto

Orion Adrian Points 8855

Les bibliothèques statiques augmentent la taille du code dans votre binaire. Elles sont toujours chargées et la version du code avec laquelle vous avez compilé est la version du code qui s'exécutera.

Les bibliothèques dynamiques sont stockées et versionnées séparément. Il est possible de charger une version de la bibliothèque dynamique qui n'est pas celle qui a été livrée avec votre code. si la mise à jour est considérée comme binairement compatible avec la version originale.

En outre, les bibliothèques dynamiques ne sont pas nécessairement chargées - elles le sont généralement lors du premier appel - et peuvent être partagées entre les composants qui utilisent la même bibliothèque (plusieurs chargements de données, un seul chargement de code).

Les bibliothèques dynamiques étaient considérées comme la meilleure approche la plupart du temps, mais elles présentaient à l'origine un défaut majeur (google DLL hell), qui a pratiquement été éliminé par les systèmes d'exploitation Windows plus récents (Windows XP en particulier).

80 votes

Sous Windows/Mac (pas de gestionnaire de paquets), il n'y a vraiment aucune raison d'utiliser des bibliothèques dynamiques plutôt que statiques. Les DLL de Windows n'étant pas relocalisables, le partage de code ne fonctionne souvent pas (et, de toute façon, chaque application livre et utilise ses propres versions de la bibliothèque). Le seul avantage réel est qu'il est plus facile de mettre à jour la bibliothèque.

1 votes

Qu'entendez-vous précisément par "délocalisable" ?

6 votes

Sur le mac, j'utilise beaucoup de bibliothèques dynamiques. par exemple, mac os x intègre sqlite3. j'ai créé un programme qui possède une fonction de base de données sqlite3 pour le stockage des performances. cependant, comme elle est rarement utilisée, la liaison dynamique permet d'économiser sur le temps de compilation, rend les tests plus faciles/rapides ; cependant, si je devais créer une version finale, je pense que j'utiliserais toujours une bibliothèque statique, juste en cas de problèmes de compatibilité.

213voto

bk1e Points 13737

D'autres ont expliqué de manière adéquate ce qu'est une bibliothèque statique, mais j'aimerais souligner certains des inconvénients de l'utilisation de bibliothèques statiques, du moins sous Windows :

  • Les singletons : Si un élément doit être global/statique et unique, faites très attention à le placer dans une bibliothèque statique. Si plusieurs DLL sont liées à cette bibliothèque statique, elles obtiendront chacune leur propre copie du singleton. Toutefois, si votre application est un EXE unique sans DLL personnalisées, cela peut ne pas être un problème.

  • Suppression du code non référencé : Lorsque vous liez une bibliothèque statique, seules les parties de la bibliothèque statique qui sont référencées par votre DLL/EXE seront liées à votre DLL/EXE.

    Par exemple, si mylib.lib contient a.obj y b.obj et que votre DLL/EXE ne fait référence qu'à des fonctions ou des variables provenant de a.obj l'intégralité de b.obj sera écarté par l'éditeur de liens. Si b.obj contient des objets globaux/statiques, leurs constructeurs et destructeurs ne seront pas exécutés. Si ces constructeurs/destructeurs ont des effets secondaires, vous pouvez être déçu par leur absence.

    De même, si la bibliothèque statique contient des points d'entrée spéciaux, vous devrez peut-être veiller à ce qu'ils soient effectivement inclus. Un exemple de ceci dans la programmation embarquée (ok, pas Windows) serait un gestionnaire d'interruption qui est marqué comme étant à une adresse spécifique. Vous devez également marquer le gestionnaire d'interruption comme un point d'entrée pour vous assurer qu'il ne sera pas supprimé.

    Une autre conséquence de ceci est qu'une bibliothèque statique peut contenir des fichiers objets qui sont complètement inutilisables à cause de références non résolues, mais elle ne provoquera pas d'erreur de liaison jusqu'à ce que vous fassiez référence à une fonction ou une variable de ces fichiers objets. Cela peut se produire longtemps après l'écriture de la bibliothèque.

  • Symboles de débogage : Il se peut que vous souhaitiez disposer d'une PDB distincte pour chaque bibliothèque statique ou que vous souhaitiez que les symboles de débogage soient placés dans les fichiers objet afin qu'ils soient intégrés dans la PDB de la DLL/EXE. La documentation de Visual C++ explique les options nécessaires .

  • RTTI : Vous pouvez vous retrouver avec plusieurs type_info pour la même classe si vous liez une seule bibliothèque statique à plusieurs DLL. Si votre programme suppose que type_info est une donnée "singleton" et utilise &typeid() o type_info::before() vous risquez d'obtenir des résultats indésirables et surprenants.

25 votes

Quant à la question des singletons, n'oubliez pas qu'une DLL peut être chargée plusieurs fois (même version ou plusieurs versions) et qu'il n'y a toujours pas de garantie de singleton.

0 votes

Point supplémentaire sur la suppression du code non référencé : Les appels faits aux DLLs nécessitent également un appel réel pour forcer le chargement de la DLL référencée. Si vous l'ajoutez en tant que référence, mais que vous n'incluez pas d'appel qui la référence, vous obtiendrez le même résultat qu'avec une bibliothèque statique qui n'appelle rien. La seule différence réside dans ce qui est réellement expédié. Dans les deux cas, les constructeurs et destructeurs statiques ne sont pas activés.

0 votes

Le fichier .a contiendra toujours tous les symboles avec lesquels il a été construit. Lorsqu'il sera lié statiquement à votre application, seuls les symboles utilisés seront liés.

72voto

Franci Penov Points 45358

Une librairie est une unité de code qui est regroupée dans l'exécutable de votre application.

Une dll est une unité autonome de code exécutable. Elle est chargée dans le processus uniquement lorsqu'un appel est effectué dans ce code. Une dll peut être utilisée par plusieurs applications et chargée dans plusieurs processus, tout en n'ayant qu'une seule copie du code sur le disque dur.

Dll pros : peut être utilisé pour réutiliser/partager le code entre plusieurs produits ; se charge dans la mémoire du processus à la demande et peut être déchargé lorsqu'il n'est pas nécessaire ; peut être mis à jour indépendamment du reste du programme.

Dll contre impact sur les performances du chargement des dll et du reformatage du code ; problèmes de versionnement ("dll hell").

Les pros de la librairie Pas d'impact sur les performances car le code est toujours chargé dans le processus et n'est pas rebasé ; pas de problèmes de version.

Lib cons pas de réutilisation/partage - chaque produit a sa propre copie du code.

0 votes

Le rebasage peut également être effectué au moment de la construction à l'aide de rebase.exe ou en passant l'option /BASE à link.exe. L'efficacité de cette méthode dépend de l'existence de conflits d'espace d'adressage inattendus au moment de l'exécution.

16voto

Vijay Points 17992

Création d'une bibliothèque statique

$$:~/static [32]> cat foo.c
#include<stdio.h>
void foo()
{
printf("\nhello world\n");
}
$$:~/static [33]> cat foo.h
#ifndef _H_FOO_H
#define _H_FOO_H

void foo();

#endif
$$:~/static [34]> cat foo2.c
#include<stdio.h>
void foo2()
{
printf("\nworld\n");
}
$$:~/static [35]> cat foo2.h
#ifndef _H_FOO2_H
#define _H_FOO2_H

void foo2();

#endif
$$:~/static [36]> cat hello.c
#include<foo.h>
#include<foo2.h>
void main()
{
foo();
foo2();
}
$$:~/static [37]> cat makefile
hello: hello.o libtest.a
        cc -o hello hello.o -L. -ltest
hello.o: hello.c
        cc -c hello.c -I`pwd`
libtest.a:foo.o foo2.o
        ar cr libtest.a foo.o foo2.o
foo.o:foo.c
        cc -c foo.c
foo2.o:foo.c
        cc -c foo2.c
clean:
        rm -f foo.o foo2.o libtest.a hello.o

$$:~/static [38]>

création d'une bibliothèque dynamique

$$:~/dynamic [44]> cat foo.c
#include<stdio.h>
void foo()
{
printf("\nhello world\n");
}
$$:~/dynamic [45]> cat foo.h
#ifndef _H_FOO_H
#define _H_FOO_H

void foo();

#endif
$$:~/dynamic [46]> cat foo2.c
#include<stdio.h>
void foo2()
{
printf("\nworld\n");
}
$$:~/dynamic [47]> cat foo2.h
#ifndef _H_FOO2_H
#define _H_FOO2_H

void foo2();

#endif
$$:~/dynamic [48]> cat hello.c
#include<foo.h>
#include<foo2.h>
void main()
{
foo();
foo2();
}
$$:~/dynamic [49]> cat makefile
hello:hello.o libtest.sl
        cc -o hello hello.o -L`pwd` -ltest
hello.o:
        cc -c -b hello.c -I`pwd`
libtest.sl:foo.o foo2.o
        cc -G -b -o libtest.sl foo.o foo2.o
foo.o:foo.c
        cc -c -b foo.c
foo2.o:foo.c
        cc -c -b foo2.c
clean:
        rm -f libtest.sl foo.o foo

2.o hello.o
$$:~/dynamic [50]>

15voto

Corey Trager Points 11334

Vous devez réfléchir soigneusement aux changements dans le temps, à la gestion des versions, à la stabilité, à la compatibilité, etc.

Si deux applications utilisent le même code, voulez-vous les obliger à changer ensemble, au cas où elles devraient être compatibles l'une avec l'autre ? Utilisez alors la dll. Tous les exe utiliseront le même code.

Ou bien voulez-vous les isoler l'un de l'autre, afin de pouvoir en modifier un tout en étant sûr de ne pas avoir cassé l'autre. Dans ce cas, utilisez la librairie statique.

L'enfer des DLL, c'est quand vous auriez probablement dû utiliser une librairie statique, mais que vous avez utilisé une DLL à la place, et que tous les ex ne sont pas compatibles avec elle.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X