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 gccpermite 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

gcc(1)

ld(1)

ldd(1)

Why do you have to link the math library in C? - Stack Overflow

The Linux FAQ - System Libraries


Tal vez pueda interesarte


Compartí este artículo