Al tratar de compilar con gcc un programa en lenguaje C me encontré con este error.
El programa en cuestión es el siguiente:
luser@debian:~$ cat cuadrado.c #include <stdio.h> #include <stdlib.h> #include <math.h> int main(int argc, char **argv) { int err = 0; if (argc > 1) { int x = atoi(argv[1]); printf("%i elevado al cuadrado es igual a %.0f.\n",x,pow(x,2)); } else { printf("Ingrese un entero como parámetro.\n"); err = 1; } return err; }
Este incluye la librería math.h
para utilizar la función pow
que calcula potencias.
Sin embargo, al momento de compilar con gcc
, el linker (ld
) arroja el error: undefined reference to `pow'
indicando que desconoce la función "pow":
luser@debian:~$ gcc -Wall -o cuadrado cuadrado.c /tmp/ccvLS0kD.o: In function `main': cuadrado.c:(.text+0x4b): undefined reference to `pow' collect2: error: ld returned 1 exit status
Para evitar este problema, es necesario indicarle al linker que cree el binario enlazando con la librería "math.h". No es suficiente con incluirlo en el fuente (eso sólo lo "ve" el compilador). La respuesta rápida en decenas de sitios de Internet indica que se debe compilar agregando la opción -lm
al final del comando:
luser@debian:~$ gcc -Wall -o cuadrado cuadrado.c -lm luser@debian:~$ ./cuadrado 21 21 elevado al cuadrado es igual a 441.
Perfecto, compila sin errores ni warnings y funciona correctamente.
Ahora bien, ¿qué indica la opción -lm
al final del comando gcc
?
Extracto del manual de gcc:
Linker Options object-file-name -llibrary -nostartfiles -nodefaultlibs -nostdlib -pie -rdynamic -s -static -static-libgcc -shared -shared-libgcc -symbolic -T script -Wl,option -Xlinker option -u symbol
El compilador gcc
permite pasar opciones al linker, las cuales deben especificarse al final del comando.
Extracto del manual del linker (ld
):
-l namespec --library=namespec Add the archive or object file specified by namespec to the list of files to link.
La opción -lm
indica al linker que enlace con la librería compartida "m", es decir "libm":
luser@debian:~$ ldd cuadrado linux-vdso.so.1 => (0x00007ffff3dfc000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f8f7432d000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f8f73fa0000) /lib64/ld-linux-x86-64.so.2 (0x00007f8f745b6000)
Esto es necesario ya que las funciones definidas en la cabecera math.h
está implementadas en la librería libm.so
. En cambio, la librería libc.so
, que implementa las funciones definidas en las cabeceras stdio.h
y stdlib.h
, es incluida por defecto.
Referencias
Why do you have to link the math library in C? - Stack Overflow
The Linux FAQ - System Libraries