Cuándo usar bibliotecas dinámicas frente a estáticas


Al crear una biblioteca de clases en C++, puede elegir entre dynamic (.dll) y static (.lib) bibliotecas. ¿Cuál es la diferencia entre ellos y cuándo es apropiado usar cuáles?

Author: Sam, 2008-09-26

18 answers

Las bibliotecas estáticas aumentan el tamaño del código en su binario. Siempre están cargados y cualquier versión de el código compilado con la versión del código que se ejecutará.

Las bibliotecas dinámicas se almacenan y versionan por separado. Es posible que se cargue una versión de la biblioteca dinámica que no fuera la original que se envió con su código si la actualización se considera compatible binaria con la versión original.

Bibliotecas dinámicas adicionales no se cargan necesariamente-normalmente se cargan cuando se llama por primera vez-y se pueden compartir entre componentes que usan la misma biblioteca (cargas de datos múltiples, una carga de código).

Las bibliotecas dinámicas se consideraban el mejor enfoque la mayor parte del tiempo, pero originalmente tenían un defecto importante (google DLL hell), que casi ha sido eliminado por los sistemas operativos de Windows más recientes (Windows XP en particular).

 269
Author: Orion Adrian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-11 20:47:29

Otros han explicado adecuadamente lo que es una biblioteca estática, pero me gustaría señalar algunas de las advertencias de usar bibliotecas estáticas, al menos en Windows:

  • Singletons: Si algo necesita ser global/estático y único, tenga mucho cuidado al ponerlo en una biblioteca estática. Si varios archivos DLL están vinculados contra esa biblioteca estática, cada uno obtendrá su propia copia del singleton. Sin embargo, si su aplicación es un solo EXE sin DLL personalizados, esto puede que no sea un problema.

  • Eliminación de código no referenciado: Cuando se vincula con una biblioteca estática, solo las partes de la biblioteca estática a las que hace referencia su DLL/EXE se vincularán a su DLL/EXE.

    Por ejemplo, si mylib.lib contiene a.obj y b.obj y su DLL/EXE solo hace referencia a funciones o variables de a.obj, el enlazador descartará la totalidad de b.obj. Si b.obj contiene objetos globales / estáticos, sus constructores y destructores no será ejecutado. Si esos constructores / destructores tienen efectos secundarios, usted puede ser decepcionado por su ausencia.

    Del mismo modo, si la biblioteca estática contiene puntos de entrada especiales, es posible que deba tener cuidado de que realmente se incluyan. Un ejemplo de esto en la programación embebida (bien, no Windows) sería un manejador de interrupciones que está marcado como en una dirección específica. También debe marcar el controlador de interrupciones como un punto de entrada para asegurarse de que no se descartar.

    Otra consecuencia de esto es que una biblioteca estática puede contener archivos objeto que son completamente inutilizables debido a referencias no resueltas, pero no causará un error de enlazador hasta que haga referencia a una función o variable de esos archivos objeto. Esto puede suceder mucho después de que se escriba la biblioteca.

  • Símbolos de depuración: Es posible que desee un PDB separado para cada biblioteca estática, o es posible que desee que los símbolos de depuración se coloquen en los archivos objeto para que obtener enrollado en el PDB para el DLL / EXE. La documentación de Visual C++ explica las opciones necesarias.

  • RTTI: Puede terminar con varios objetos type_info para la misma clase si vincula una sola biblioteca estática a varias DLL. Si su programa asume que type_info son datos "singleton" y utiliza &typeid() o type_info::before(), puede obtener resultados indeseables y sorprendentes.

 179
Author: bk1e,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-26 16:17:37

Una lib es una unidad de código que se incluye dentro del ejecutable de su aplicación.

Una dll es una unidad independiente de código ejecutable. Se carga en el proceso solo cuando se realiza una llamada a ese código. Una dll puede ser utilizada por múltiples aplicaciones y cargada en múltiples procesos, sin dejar de tener una sola copia del código en el disco duro.

Dll pros : se puede utilizar para reutilizar / compartir código entre varios productos; carga en la memoria de proceso bajo demanda y se puede descargar cuando no es necesario; se puede actualizar independientemente del resto del programa.

Dll cons : impacto en el rendimiento de la carga dll y el cambio de base de código; problemas de versiones ("dll hell")

Lib pros : no hay impacto en el rendimiento, ya que el código siempre se carga en el proceso y no se rebasa; no hay problemas de versiones.

Lib cons : ejecutable / proceso "bloat" - todo el código está en su ejecutable y se carga al inicio del proceso; no reutilizar / compartir-cada producto tiene su propia copia del código.

 55
Author: Franci Penov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-04 13:05:24

Además de las implicaciones técnicas de las bibliotecas estáticas vs dinámicas (los archivos estáticos agrupan todo en un gran binario vs bibliotecas dinámicas que permiten compartir código entre varios ejecutables diferentes), están las implicaciones legales .

Por ejemplo, si está utilizando código con licencia LGPL y enlaza estáticamente contra una biblioteca LGPL (y así crea un binario grande), su código automáticamente se convierte en código abierto (libre como en libertad) Código LGPL. Si se enlaza contra a objetos compartidos, entonces solo necesita LGPL las mejoras / correcciones de errores que realice en la biblioteca LGPL en sí.

Esto se convierte en un tema mucho más importante si está decidiendo cómo compilar aplicaciones móviles, por ejemplo (en Android tiene una opción de estática vs dinámica, en iOS no, siempre es estática).

 19
Author: rburhum,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-10 01:44:26

Creando una biblioteca estática

$$:~/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]>

Creando una biblioteca dinámica

$$:~/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]>
 17
Author: Vijay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-14 12:38:34

Debe pensar cuidadosamente en los cambios a lo largo del tiempo, el control de versiones, la estabilidad, la compatibilidad, etc.

Si hay dos aplicaciones que usan el código compartido, ¿desea forzar a esas aplicaciones a cambiar juntas, en caso de que necesiten ser compatibles entre sí? A continuación, utilice el dll. Todos los exe usarán el mismo código.

O quieres aislarlos entre sí, para que puedas cambiar uno y estar seguro de que no has roto el otro. A continuación, utilice la estática lib.

DLL el infierno es cuando probablemente deberías haber usado una lib estática, pero usaste una dll en su lugar, y no todos los exes son comaptibles con ella.

 12
Author: Corey Trager,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-26 15:25:46

Los programas C++ se construyen en dos fases

  1. Compilación - produce código objeto (.obj)
  2. Vinculación-produce código ejecutable (.exe or .dll)

Biblioteca Estática (.lib) es solo un paquete de .obj archivos y por lo tanto no es un programa completo. No ha pasado por la segunda fase (enlace) de la construcción de un programa. Dlls, por otro lado, son como exe y por lo tanto son programas completos.

Si construye una biblioteca estática, todavía no está vinculada y, por lo tanto, los consumidores de tu biblioteca estática tendrán que usar el mismo compilador que usaste (si usaste g++, tendrán que usar g++).

Si en su lugar construiste un dll (y lo construiste correctamente), has construido un programa completo que todos los consumidores pueden usar, sin importar qué compilador estén usando. Sin embargo, hay varias restricciones al exportar desde una dll, si se desea la compatibilidad con el compilador cruzado.

 12
Author: tcb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-09 01:29:28

Una biblioteca estática se compila en el cliente. Un .lib se utiliza en tiempo de compilación y el contenido de la biblioteca se convierte en parte del ejecutable consumidor.

Una biblioteca dinámica se carga en tiempo de ejecución y no se compila en el ejecutable del cliente. Las bibliotecas dinámicas son más flexibles ya que varios ejecutables de cliente pueden cargar una DLL y utilizar su funcionalidad. Esto también mantiene el tamaño general y la capacidad de mantenimiento de su código de cliente a un mínimo.

 10
Author: Jordan Parmer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-26 15:05:56

Una biblioteca estática debe estar vinculada al ejecutable final; se convierte en parte del ejecutable y lo sigue dondequiera que vaya. Una biblioteca dinámica se carga cada vez que se ejecuta el ejecutable y permanece separada del ejecutable como un archivo DLL.

Se usaría una DLL cuando se desea poder cambiar la funcionalidad proporcionada por la biblioteca sin tener que volver a vincular el ejecutable (simplemente reemplazar el archivo DLL, sin tener que reemplazar el archivo ejecutable).

Usted usaría una biblioteca estática siempre que no tenga una razón para usar una biblioteca dinámica.

 7
Author: spotcatbug,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-26 15:08:20

El artículo de Ulrich Drepper sobre "Cómo escribir Bibliotecas Compartidas" también es un buen recurso que detalla la mejor manera de aprovechar las bibliotecas compartidas, o lo que se refiere como "Objetos Compartidos Dinámicos" (DSO). Se centra más en bibliotecas compartidas en el formato binario ELF, pero algunas discusiones también son adecuadas para DLL de Windows.

 7
Author: Void,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-11 22:44:13

Para una excelente discusión de este tema, lea este artículo de Sun.

Entra en todos los beneficios incluyendo la posibilidad de insertar bibliotecas de interposición. Puede encontrar más detalles sobre la interposición en este artículo aquí.

 5
Author: Rob Wells,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-26 16:17:27

Realmente el intercambio que está haciendo (en un proyecto grande) es en el tiempo de carga inicial, las bibliotecas se van a vincular en un momento u otro, la decisión que debe tomarse es si el enlace tomará el tiempo suficiente para que el compilador necesite morder la bala y hacerlo por adelantado, o puede el enlazador dinámico hacerlo en el tiempo de carga.

 4
Author: pfranza,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-26 16:01:58

Si su biblioteca va a ser compartida entre varios ejecutables, a menudo tiene sentido hacerlo dinámico para reducir el tamaño de los ejecutables. De lo contrario, definitivamente hacerlo estático.

Hay varias desventajas de usar una dll. Hay sobrecarga adicional para cargarlo y descargarlo. También hay una dependencia adicional. Si cambia la dll para que sea incompatible con sus executalbes, dejarán de funcionar. Por otro lado, si cambia una biblioteca estática, sus ejecutables compilados usando la versión anterior no se verán afectados.

 3
Author: Dima,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-26 15:05:21

Si la biblioteca es estática, entonces en el momento del enlace el código está vinculado con su ejecutable. Esto hace que su ejecutable sea más grande (que si fuera la ruta dinámica).

Si la biblioteca es dinámica, en el momento del enlace se construyen referencias a los métodos requeridos en el ejecutable. Esto significa que usted tiene que enviar su ejecutable y la biblioteca dinámica. También debe considerar si el acceso compartido al código en la biblioteca es seguro, la dirección de carga preferida, entre otras cosa.

Si puede vivir con la biblioteca estática, vaya con la biblioteca estática.

 3
Author: Seb Rose,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-26 15:11:12

Las bibliotecas estáticas son archivos que contienen el código objeto de la biblioteca, cuando se vinculan a una aplicación, ese código se compila en el ejecutable. Las bibliotecas compartidas son diferentes en que no están compiladas en el ejecutable. En su lugar, el enlazador dinámico busca en algunos directorios las bibliotecas que necesita, y luego las carga en la memoria. Más de un ejecutable puede usar la misma biblioteca compartida al mismo tiempo, reduciendo así el uso de memoria y el tamaño del ejecutable. Sin embargo, hay son entonces más archivos para distribuir con el ejecutable. Debe asegurarse de que la biblioteca esté instalada en el sistema uses en algún lugar donde el enlazador pueda encontrarla, el enlace estático elimina este problema pero da como resultado un archivo ejecutable más grande.

 2
Author: Terence Simpson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-26 15:08:22

Si su trabajo en proyectos embebidos o plataformas especializadas bibliotecas estáticas son el único camino a seguir, también muchas veces son menos de una molestia para compilar en su aplicación. También tener proyectos y makefile que incluyen todo hace la vida más feliz.

 2
Author: Robert Gould,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-26 15:16:56

Usamos muchas DLL (> 100) en nuestro proyecto. Estas DLL tienen dependencias entre sí y, por lo tanto, elegimos la configuración del enlace dinámico. Sin embargo tiene las siguientes desventajas:

  • inicio lento (>10 segundos)
  • Las DLL tuvieron que ser versionadas, ya que windows carga módulos sobre la unicidad de los nombres. De lo contrario, los componentes escritos propios obtendrían la versión incorrecta de la DLL (es decir, la que ya está cargada en lugar de su propio conjunto distribuido)
  • el optimizador solo puede optimiza dentro de los límites de DLL. Por ejemplo, el optimizador intenta colocar los datos y el código utilizados con frecuencia uno al lado del otro, pero esto no funcionará a través de los límites de DLL

Tal vez una mejor configuración fue hacer todo una biblioteca estática (y por lo tanto solo tiene un ejecutable). Esto solo funciona si no hay duplicación de código. Una prueba parece apoyar esta suposición, pero no pude encontrar una cita oficial de MSDN. Así, por ejemplo, hacer 1 exe con:

  • exe usos shared_lib1, shared_lib2
  • shared_lib1 use shared_lib2
  • shared_lib2

El código y las variables de shared_lib2 deben estar presentes en el ejecutable fusionado final solo una vez. ¿Alguien puede apoyar esta pregunta?

 2
Author: gast128,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-02 08:22:10

Le daría una regla general que si tiene una base de código grande, todo construido sobre bibliotecas de nivel inferior (por ejemplo, un marco Utils o Gui), que desea particionar en bibliotecas más manejables y luego convertirlas en bibliotecas estáticas. Las bibliotecas dinámicas realmente no te compran nada y hay menos sorpresas there solo habrá una instancia de singletons, por ejemplo.

Si tiene una biblioteca que está completamente separada del resto del código base (por ejemplo, una biblioteca de terceros) entonces considera convertirlo en un dll. Si la biblioteca es LGPL es posible que necesite usar una dll de todos modos debido a las condiciones de licencia.

 1
Author: the_mandrill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-02 08:34:05