web-dev-qa-db-fra.com

Pourquoi la liaison statique de la glibc est-elle déconseillée?

La plupart des sources en ligne indiquent que vous pouvez lier statiquement la glibc, mais découragez de le faire; par exemple. dépôt du paquet centos :

The glibc-static package contains the C library static libraries
for -static linking.  You don't need these, unless you link statically,
which is highly discouraged.

Ces sources disent rarement (ou jamais) pourquoi ce serait une mauvaise idée.

39
pzelasko

Les raisons données dans d'autres réponses sont correctes, mais ce n'est pas la raison la plus importante.

La raison la plus importante pour laquelle la glibc ne devrait pas être liée statiquement, est qu'elle utilise largement en interne dlopen , pour charger les modules NSS ( Name Service Switch ) et iconv conversions. Les modules eux-mêmes font référence aux fonctions de la bibliothèque C. Si le programme principal est lié dynamiquement à la bibliothèque C, ce n'est pas un problème. Mais si le programme principal est lié statiquement à la bibliothèque C, dlopen doit aller charger une seconde copie de la bibliothèque C pour satisfaire les exigences de charge des modules.

Cela signifie que votre programme "lié statiquement" a toujours besoin d'une copie de libc.so.6 pour être présent sur le système de fichiers, plus le NSS ou iconv ou les modules eux-mêmes, ainsi que d'autres bibliothèques dynamiques dont les modules pourraient avoir besoin, comme ld-linux.so.2, libresolv.so.2, etc. Ce n'est pas ce que les gens veulent habituellement lorsqu'ils lient statiquement des programmes.

Cela signifie également que le programme lié statiquement a deux copies de la bibliothèque C dans son espace d'adressage, et ils pourraient se battre pour savoir quel stdout tampon doit être utilisé, qui peut appeler sbrk avec un zéro argument, ce genre de chose. Il y a un tas de logique défensive à l'intérieur de la glibc pour essayer de faire fonctionner cela, mais il n'a jamais été garanti de fonctionner.

Vous pensez peut-être que votre programme n'a pas à s'en soucier car il n'appelle jamais getaddrinfo ou iconv, mais le support local utilise iconv en interne, ce qui signifie tout stdio.h fonction peut déclencher un appel à dlopen, et vous ne contrôlez pas cela, les paramètres de variable d'environnement de l'utilisateur le font.

30
zwol

Les correctifs de bogues dans la glibc ne sont pas inclus dans une application liée statiquement lorsque vous mettez à niveau la glibc, sauf si vous reconstruisez l'application.

De plus, NSS (Name Service Switch) ne fonctionne que si vous utilisez la liaison dynamique.

1
S.S. Anne

L'interface programme/glibc est normalisée et documentée par POSIX, les normes C et C++ et autres. Par exemple, la fonction fopen() se comporte conformément au standard C et pthread_mutex_lock() par POSIX.

L'interface glibc/kernel est pas standardisée. Est-ce que fopen() utilise open() sous le capot? Ou utilise-t-il openat()? Ou autre chose? Que va-t-il utiliser l'année prochaine? Tu ne sais pas.

Si l'interface glibc/kernel change, un programme qui utilise ce qui a changé mais lie statiquement glibc ne fonctionnera plus.

Il y a plus de 15 ans, Solaris a supprimé toutes les versions statiques de libc pour cette raison.

Liaison statique - où est-elle passée?

Avec Solaris 10, vous ne pouvez plus créer d'exécutable statique. Ce n'est pas que ld (1) n'autorise pas la liaison statique ou l'utilisation d'archives, c'est juste que libc.a, la version archive de libc.so.1, n'est plus fournie. Cette bibliothèque fournit les interfaces entre l'espace utilisateur et le noyau, et sans cette bibliothèque, il est plutôt difficile de créer une forme d'application.

Nous avertissons les utilisateurs contre les liens statiques depuis un certain temps maintenant, et les liens contre libc.a ont été particulièrement problématiques. Chaque version de Solaris, ou mise à jour (même certains correctifs) a entraîné l'échec de certaines applications construites contre libc.a. Le problème est que libc est censé isoler une application de la frontière utilisateur/noyau, une frontière qui peut subir des changements de version en version.

Si une application est construite sur libc.a, , alors toute interface du noyau qu'elle référence est extraite de l'archive et devient une partie de l'application. Ainsi, cette application ne peut s'exécuter que sur un noyau synchronisé avec les interfaces du noyau utilisées. Si ces interfaces changent, l'application marche sur un terrain instable.

...

Modifier:

Il semble y avoir une sérieuse surestimation de la stabilité de l'interface du noyau Linux. Voir Modifications/ajouts de l'API du noyau Linux pour plus de détails. Résumer:

enter image description here

0
Andrew Henle