Bien. Cuando se incluye math.h
, el compilador leerá el archivo que contiene las declaraciones de las funciones y macros que se pueden usar. Si llama a una función declarada en ese archivo (encabezado), el compilador inserta una instrucción de llamada en ese lugar en su archivo de objeto que se creará desde el archivo que compila (llamémoslo test.c
y el archivo de objeto creado test.o
) . También agrega una entrada en la tabla de reubicación de ese objeto-archivo:
Relocation section '.rel.text' at offset 0x308 contains 1 entries:
Offset Info Type Sym.Value Sym. Name
0000001c 00000902 R_386_PC32 00000000 bar
Esta sería una entrada de reubicación para una barra de funciones.Una entrada en la tabla de símbolos se hará teniendo en cuenta la función aún no está definido:
9: 00000000 0 NOTYPE GLOBAL DEFAULT UND bar
Al vincular el archivo test.o
objeto en un programa, es necesario enlazar con la biblioteca matemática llamada libm.so
. La extensión so
es similar a la extensión .dll
para Windows. Significa que es un archivo de objeto compartido . El compilador, al vincular, reparará todos los lugares que aparecen en la tabla de reubicación test.o
, reemplazando sus entradas con la dirección correcta de la función de la barra. Dependiendo de si usa la versión compartida de la biblioteca o la estática (se llama libm.a
), el compilador hará esa reparación después de la compilación, o más tarde, en tiempo de ejecución cuando realmente inicie su programa. Cuando termine, inyectará una entrada en la tabla de bibliotecas compartidas necesarias para ese programa. (Se pueden mostrar con readelf -d ./test
):
Dynamic section at offset 0x498 contains 22 entries:
Tag Type Name/Value
0x00000001 (NEEDED) Shared library: [libm.so.6]
0x00000001 (NEEDED) Shared library: [libc.so.6]
... ... ...
Ahora bien, si se inicia el programa, el enlazador dinámico de búsqueda que la biblioteca, y unirá esa biblioteca a su imagen ejecutable. En Linux, el programa que hace esto se llama ld.so
. Las bibliotecas estáticas no tienen un lugar en la sección dinámica, ya que solo están vinculadas a los otros archivos de objetos y luego se olvidan de ellas; son parte del ejecutable a partir de ese momento.
En realidad, es mucho más complejo y tampoco lo entiendo en detalle. Ese es el plan aproximado, sin embargo.
No mencionaste cómo vincularlo ... pero creo que el resto del detalle lo compensa. –
Como siempre, una respuesta muy reflexiva, lúcida e integral. +1 solo porque no hay un +3. –
La vinculación o generación de código realmente no tiene nada que ver con #includes embargo. La parte más complicada sobre #include es qué tan sencillo es, y cómo la generación de código y los enlaces están completamente separados de esto. – jalf