¿Las bibliotecas estáticas en C están mal vistas? [cerrado]

11

Hay 2 argumentos para tener bibliotecas compartidas:

  1. Ayuda a reducir el espacio en disco.
  2. Cuando se actualiza una biblioteca compartida, todos los binarios que dependen de ella obtienen la actualización.

Hay principalmente un inconveniente para las bibliotecas compartidas:

  • Ellos (pueden) introducir el infierno de dependencia.

En las computadoras de escritorio, la primera ventaja ya no es válida. La pérdida de espacio en disco no es un gran problema en estos días.

Tener archivos binarios estáticos nos permitiría ser mucho mejores administradores de paquetes; quiero decir, el infierno de la dependencia sería cosa del pasado. Agregar un programa sería simplemente agregar un binario; finalmente una carpeta para permitirle manejar sus archivos. Eliminar un programa sería simplemente eliminar este archivo. Dependencias? Ido.

La segunda ventaja sigue en pie, pero creo que la ventaja de los binarios estáticos en las computadoras de escritorio lo supera. Quiero decir, incluso los nuevos lenguajes como Go compilan todos sus binarios a pesar de las ventajas de las bibliotecas compartidas, debido a la conveniencia.


Dado que una de las principales ventajas de las bibliotecas compartidas ya no es un gran problema, ¿las bibliotecas estáticas en C todavía están mal vistas? Si es así, ¿por qué?

Florian Margaine
fuente
44
La razón principal de que C se utiliza más específicamente es porque estás no trabajar en las computadoras de escritorio modernas.
Telastyn
18
@Telastyn lo siento? La mayor parte del software instalado en mis computadoras de escritorio está escrito en C.
Florian Margaine
66
Bit lateral - un sitio
66
Una ventaja de las bibliotecas dinámicas es que las personas aún pueden actualizar las bibliotecas para evitar errores, agujeros de seguridad o problemas de hardware en su juego de código cerrado de 15 años que hace mucho tiempo dejó de recibir actualizaciones. Es un caso de nicho, pero como los buenos juegos no son productos básicos, "simplemente usar otro programa" realmente no ayuda. También es importante para cumplir con LGPL sin abrir su propio código.
Doval
44
Olvidó otras dos ventajas de las bibliotecas compartidas: 1) también se comparten en la memoria, 2) todos los enlazadores apestan mal, y vincular un gran binario es muy desagradable. Dividir un binario en varias entidades más pequeñas hace que todo el proceso sea mucho más tolerable.
SK-logic

Respuestas:

9

La premisa de su pregunta es errónea. Lo que está mal visto es apegarse a doctrinarios y absolutos sin entender la base detrás de ellos (¿Programación de culto de carga?).

La respuesta SO vinculada es un estudio interesante en ese mismo tema: la pregunta era sobre por qué una compilación con la opción estática no funcionaba, la respuesta a la que se vinculó no fue más que una queja sobre no usar la vinculación estática. Si no discute por qué es malo, y exige que el OP utilice enlaces dinámicos. Es desafortunado que esté marcado como la respuesta correcta (la siguiente respuesta tiene el doble de votos y es la respuesta correcta a la pregunta del OP) porque aunque la respuesta correcta está allí, está profundamente oculta entre una opinión dogmática.

La verdadera pregunta es cuáles son los pros y los contras de los enlaces estáticos frente a los dinámicos y cuándo se preferiría uno sobre el otro.

Mattnz
fuente
2
La respuesta de Basile hace le dirá exactamente por qué se recomienda el uso de bibliotecas compartidas: ? "¿Por qué quiere enlace estáticamente su aplicación . Por lo general, es un error (porque no lo hace se benefician de cambios a las librerías dinámicas del sistema) En particular Name Service Switch instalaciones de libc quiere bibliotecas dinámicas " . No es una" queja "simplemente porque no está de acuerdo con ella.
Cody Gray
@Cody La respuesta vinculada a ha sido editada desde que la llamé despotricar. La única opinión que tengo sobre la vinculación estática frente a la dinámica es usar la que sea apropiada para sus necesidades y comprender las fortalezas y debilidades de la elección en lugar de caer en la doctrina de programación de culto de carga porque "alguien lo dijo".
mattnz
Sí, se agregó la parte "En particular ...". No estoy seguro de cómo eso afecta su estado de despotricar. Por supuesto que no estoy abogando por la programación de culto de carga. Es solo que los defensores de los enlaces estáticos (en mi experiencia) a menudo pierden o subestiman las preocupaciones de seguridad. La vinculación estática puede ser muy apropiada para utilidades únicas, lo que hace que la aplicación sea autónoma y, por lo tanto, la distribución sea mucho más fácil. Pero cualquier aplicación que se implemente ampliamente o se use para la producción realmente debería vincularse a una biblioteca compartida. No existen desventajas reales: en este nivel de aplicación, ya necesita un proceso de implementación.
Cody Gray
1
Un buen ejemplo de dónde es apropiado el enlace estático es donde trabajo: sistemas críticos de vida grandes y complejos. Una vez que un módulo crítico es probado y aprobado para su funcionamiento, su comportamiento no debe cambiar sin pasar por "el proceso". Sin embargo, ninguna parte operacional y no vital del sistema (facturación e informes) necesita un control menos robusto y utiliza enlaces dinámicos.
mattnz
7

Desde el punto de vista del desarrollador, la vinculación dinámica a menudo puede acelerar considerablemente su compilación / enlace / bucle de prueba.

Desde el punto de vista de la gestión de paquetes, tome libGL, por ejemplo. Tengo aproximadamente una docena de implementaciones diferentes disponibles en mi administrador de paquetes, algunas genéricas y otras específicas para tarjetas gráficas. Si no estuviera vinculado dinámicamente, tendría que haber una docena de versiones de cada programa que se vincule con libGL, o de lo contrario tendría que idear una capa adicional de abstracción que no sea tan eficiente como una llamada de función.

Piense en un problema de seguridad en una biblioteca popular como Qt. Con el enlace dinámico, puedo actualizar ese paquete, en lugar de tener que identificar, recompilar e implementar cada paquete que se vincule en Qt.

La vinculación estática puede tener ventajas en aplicaciones de código cerrado implementadas independientemente, pero en la gestión de paquetes de código abierto duele más de lo que ayuda.

Karl Bielefeldt
fuente
2
Esto es cierto (acelerar el desarrollo), pero es realmente frustrante que llegue a producción. El ejemplo canónico es Firefox. La cantidad de esfuerzo de ingeniería (en forma de hacks horribles) que se ha invertido en acelerar la resolución dinámica de los símbolos de enlace para que Firefox se cargue en un tiempo razonable es una locura. Se podría haber logrado un rendimiento mucho mejor con un costo de ingeniería mucho menor si solo estuvieran dispuestos a vincular de forma estática todo su código dentro del proyecto (mientras aún vinculaban dinámicamente bibliotecas y complementos del sistema, si lo deseaban).
R .. GitHub DEJA DE AYUDAR A HIELO
5

Las bibliotecas compartidas son muy preferidas por los mantenedores de distribución de Linux básicamente por su razón # 2. Es realmente importante para ellos que, por ejemplo, cuando alguien encuentre un error de seguridad en zlib , no tengan que recompilar cada uno de los programas que usan zlib --- no solo les costaría más ciclos de CPU hacer el Al volver a compilar, todos los que usan la distribución tendrían que volver a descargar todos esos programas. Mientras tanto, dentro del conjunto de paquetes proporcionados por una distribución, el infierno de dependencia no es un problema, porque todo se prueba para que funcione con ese conjunto de bibliotecas.

Si está creando software de terceros que necesita bibliotecas que no están en su distribución, entonces vincular estáticamente esas bibliotecas puede ser menos complicado que la alternativa, y eso está bien.

La otra cosa importante que debe saber es que GNU libcy GCC libstdc++tienen componentes que no funcionan de manera confiable si la biblioteca está estáticamente vinculada. El problema más común es con dlopen, porque cualquier módulo con el que cargue dlopenestá vinculado dinámicamentelibc.so.6 . Eso significa que ahora tiene dos copias de la biblioteca C en su espacio de direcciones, y se produce hilaridad cuando no están de acuerdo sobre qué copia de la mallocestructura de datos interna (por ejemplo) es autorizada. Pero hay algo peor: un montón de funciones que no parece tener nada que ver con dlopen, al igual que gethostbynamey iconv, el usodlopeninternamente (para que su comportamiento sea configurable en tiempo de ejecución). Afortunadamente, el ABI para libc y libstdc ++ es muy estable, por lo que es poco probable que encuentre problemas para vincularlos dinámicamente.

zwol
fuente
2

Estoy de acuerdo con el último punto de mattnz: esta pregunta es una pregunta cargada. Se supone que el enlace estático es malo. Puedo pensar en dos razones por las cuales este no es el caso:

  • La vinculación estática es segura: si una biblioteca compartida se actualiza de modo que una aplicación use la nueva (tal vez la nueva sobrescriba la anterior o se elimine la anterior), puede introducir el riesgo de que la nueva versión rompa la aplicación. Este es un cambio de código fuera del alcance de una actualización oficial de la aplicación. Puede que no haya sido probado. La vinculación estática evita esto al no compartir bibliotecas externamente. Sostengo que esto es una desventaja para las bibliotecas compartidas debido a este riesgo. ¿Qué sucede si una nueva versión de una biblioteca compartida presenta un nuevo error que rompe ciertas aplicaciones antiguas?

  • La vinculación estática garantiza que una aplicación sea más autónoma. Si bien las bibliotecas compartidas se pueden ubicar con el ejecutable principal, a menudo se depositan en ubicaciones compartidas. Las aplicaciones vinculadas estáticamente son más fáciles de garantizar "portátiles" en el sentido de que "no requieren cambios en los archivos, directorios o configuraciones propiedad del sistema operativo" (piense en el directorio, registro, / etc. de Windows).


fuente
Gracias por mejorar las ventajas que quería mencionar. Sin embargo, si ve la mayoría de los paquetes proporcionados por las distribuciones de Linux, por ejemplo, no están compilados estáticamente. Que no parece que la compilación estática está mal visto, al menos desde un punto de vista externo.
Florian Margaine
1
Las bibliotecas dinámicas en casi todos los sistemas operativos que existen en estos días están paginas por demanda. Solo las páginas que realmente se utilizan están en la memoria. Si varias aplicaciones usan la misma funcionalidad, compartirán la memoria y usarán menos que el caso de la biblioteca estática. Si varias aplicaciones están utilizando diferentes funciones en la misma biblioteca, ambos conjuntos de funcionalidades serán paginados, teniendo aproximadamente el mismo impacto que el enfoque estático.
Alan Shutko
@AlanShutko Luché y reescribí esa porción de varias maneras debido a lo que mencionaste. No hay garantías reales de ninguna manera, incluso si los sistemas operativos modernos ofrecen en la práctica la eficiencia de las bibliotecas compartidas con la sobrecarga de estática. Lo editaré de nuevo.
@Snowman Creo que el punto básico es que en cualquier sistema operativo realista que proporcione enlaces dinámicos (no conozco ningún sistema operativo que use enlaces dinámicos pero no exija paginación) su segundo punto no aguanta: la memoria no se usa realmente a menos que se utilice la función y la memoria utilizada por una biblioteca dinámica se pueda compartir entre diferentes programas que la utilizan, lo que hace que el uso de la memoria para la versión dinámica sea más eficiente en lugar de menos. Sus razones primera y tercera son válidas, pero simplemente eliminaría la segunda: con cualquier suposición realista, simplemente está mal.
Jules
@Jules Estoy de acuerdo, es un punto problemático y de dudosa validez en los sistemas operativos modernos. Lo quité.
1

Las bibliotecas estáticas y dinámicas tienen sus propios usos. Al observar una sola aplicación en su alcance, obtenemos una idea diferente sobre lo que es necesario y lo que no.

La vinculación estática simplifica drásticamente la implementación de aplicaciones. No tener que detectar y lidiar con diferentes versiones. Solo hornea y despliega.

La ventaja obvia con las bibliotecas dinámicas es la capacidad de aplicar actualizaciones de forma independiente.

Esta es una de las razones por las que odio a Maven y otros creadores de proyectos de vinculación dinámica similares para Java. Esperan que una única versión de la biblioteca esté disponible en una URL dada por siempre y para siempre. No entiendo el problema que ocurre en 10 años cuando nadie puede compilar la aplicación porque toda la fuente y los frascos se han ido.

muchas patatas fritas
fuente
¿Hay alguna razón en particular por la cual no debería ser posible que los programas que FooLib1.8solían incluir el código de esa biblioteca en su paquete ejecutable de una manera estándar, para permitir que una utilidad de actualización incluida lo FooLib1.9actualice o rebaje? La forma en que se almacenó el código en Classic Macintosh lo habría hecho bastante fácil; ¿Hay alguna razón por la cual los sistemas actuales no puedan hacerlo aún mejor?
supercat
@supercat, ¿quiere decir que todas las versiones de una biblioteca determinada estarían disponibles en el sistema? No estoy seguro de entender la pregunta. La pregunta de OP se dirigió más a bibliotecas compartidas de todo el sistema que a bibliotecas estáticas que se empaquetarían juntas.
muchas patatas fritas
Mi punto es que tener un paquete ejecutable que incluya todas las bibliotecas que necesita no debería impedir la posibilidad de actualizar las bibliotecas que contiene. Por lo tanto, no sé si consideraría la posibilidad de actualizar las cosas después de la implementación como una ventaja de no agrupar una aplicación con sus bibliotecas.
supercat
Si la licencia de una biblioteca determinada le permite distribuirla con su paquete, esa es siempre la forma preferida de hacerlo. Reduce el número de dependencias externas. Como distribuiría todo, una mecánica de actualización o parche funcionaría de la misma manera con estática o dinámica. Los parches generalmente se basan en deltas binarios. No habría diferencia
montón de patatas fritas