2010-01-08 7 views
14

Tengo un ejecutable de C++ y estoy vinculando dinámicamente contra varias bibliotecas (Boost, Xerces-c y libs personalizadas).¿Por qué el enlazador de C++ requiere los archivos de la biblioteca durante una compilación, aunque estoy vinculando dinámicamente?

Entiendo por qué necesitaría los archivos .lib/.a si elijo vincular estáticamente con estas bibliotecas (relevant SO question here). Sin embargo, ¿por qué debo proporcionar los archivos correspondientes de la biblioteca .lib/.so al vincular mi ejecutable si estoy de forma dinámica enlazando con estas bibliotecas externas?

+2

El vinculador necesita saber * qué * DLL contiene una exportación que necesita resolver. El archivo .lib proporciona esta información. –

Respuesta

8

El compilador no tiene conocimiento de la vinculación dinámica, simplemente sabe que existe una función a través de su prototipo. El vinculador necesita los archivos lib para resolver el símbolo. La lib para una DLL contiene información adicional como en qué DLL viven las funciones y cómo se exportan (por nombre, por ordinal, etc.) Los archivos lib para DLL contienen mucha menos información que los archivos lib que contienen el código completo del objeto - libcmmt .lib en mi sistema es de 19.2 MB, pero msvcrt.lib es "solo" 2.6 MB.

Tenga en cuenta que este modelo de compilación/enlace tiene casi 40 años en este momento, y es anterior a los enlaces dinámicos en la mayoría de las plataformas. Si se diseñó hoy, la vinculación dinámica sería un ciudadano de primera clase (por ejemplo, en .NET, cada ensamblaje tiene metadatos enriquecidos que describen exactamente lo que exporta, por lo que no necesita encabezados y libs separados).

+3

Por lo tanto, si entiendo esto correctamente: como alternativa al enlace "implícitamente" dinámicamente (enlace contra .lib durante la compilación, use el DLL en tiempo de ejecución) - pude vincular "explícitamente" en tiempo de ejecución al usar (en Windows) LoadLibrary() para cargar el DLL y GetProcAddress() para devolver un puntero de función al método que estoy llamando. Es más código para escribir, pero no necesitaría .lib en tiempo de compilación. –

+0

Tu comprensión es correcta. – Michael

1

Para Una cosa es que el vinculador inserta las versiones de las bibliotecas que existen en el momento del enlace para que tenga alguna posibilidad de que su programa funcione si las versiones de la biblioteca se actualizan. Varias versiones de bibliotecas compartidas pueden existir en un sistema.

1

El vinculador tiene la tarea de validar que se tengan en cuenta todos los símbolos no definidos, ya sea con contenido estático o dinámico.

Por defecto, insiste en que todos sus símbolos estén presentes.

Sin embargo, eso es solo lo predeterminado. Ver -z, y --allow-shlib-undefined, y amigos.

0

Quizás este enlace dinámico se realice a través de bibliotecas de importación (la función tiene __declspec (dllimport) antes de la definición).
Si esta es la forma en que el compilador espera que exista la función __imp_symbol declarada y esta función es responsable de reenviar la llamada a la biblioteca correcta cargada dinámicamente.
Esas funciones se generan durante la vinculación de símbolos con la palabra clave __declspec (dllimport)

2

Raymond Chen escribió un par de entradas de blog sobre este específico para Windows. Comience con The classical model for linking y luego haga un seguimiento con Why do we have import libraries anyway?.

En resumen, history ha definido el compilador como el componente que conoce la información de tipo detallada, mientras que el vinculador solo conoce los nombres de los símbolos. Entonces, el enlazador termina creando el .DLL sin tipo de información y, por lo tanto, los programas que desean vincularlo necesitan algún tipo de metadato para contarle cómo se exportan las funciones y qué tipos de parámetros toman y devuelven.

La razón por la cual los .DLL no tienen toda la información que necesita para enlazar directamente con ellos es histórica, y no es una limitación técnica.

0

Aquí hay una descripción muy SIMPLIFICADA que puede ayudar. El enlace estático pone todo el código necesario para ejecutar su programa en el ejecutable para que se encuentre todo. La vinculación dinámica significa que parte del código requerido no se coloca en el ejecutable y se encontrará en el tiempo de ejecución. ¿Donde lo encuentro? Es la función x() allí?¿Cómo hago una llamada para que funcione x()? Eso es lo que la biblioteca le dice al vinculador cuando está vinculando dinámicamente.

Cuestiones relacionadas