gcc no incluirá correctamente math.h

gcc no incluirá correctamente math.h


Aquí hay un ejemplo mínimo que describe mi problema


prueba.c:


#include <stdio.h>
#include <math.h>
main ()
{
fmod ( 3, 2 );
}

Y aquí está el comando que estoy emitiendo para compilar test.c


gcc -lm test.c -o test

Y aquí está el resultado que obtengo cuando ejecuto el comando anterior


/tmp/ccQmRk99.o: In function `main':
test.c:(.text+0x3e): undefined reference to `fmod'
collect2: ld returned 1 exit status

Obtengo el mismo resultado si en su lugar uso cc . Estoy usando la siguiente versión de gcc


gcc-4.6.real (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1

¿Alguna idea de por qué mi programa no compila?


Respuestas:


El problema proviene del enlazador, ld , en lugar de gcc (de ahí el mensaje de estado de salida). En general, ld requiere que los objetos y bibliotecas se especifiquen en el orden user supplier , donde user es un objeto que usa una función de biblioteca y supplier es el objeto que lo proporciona.


Cuando tu test.c se compila en un objeto, el compilador afirma que fmod es una referencia indefinida


$ gcc -c test.c
$ nm test.o
U fmod
0000000000000000 T main

(nm enumera todas las funciones a las que hace referencia un archivo de objeto)


El enlazador cambia las referencias indefinidas a las definidas, buscando las referencias para ver si se proporcionan en otros archivos.


$ gcc -lm test.o
$ nm a.out
0000000000600e30 d _DYNAMIC
0000000000600fe8 d _GLOBAL_OFFSET_TABLE_
00000000004006a8 R _IO_stdin_used
w _Jv_RegisterClasses
0000000000600e10 d __CTOR_END__
...
0000000000601018 D __dso_handle
w __gmon_start__
...
U [email protected]@GLIBC_2.2.5
0000000000601020 A _edata
0000000000601030 A _end
0000000000400698 T _fini
0000000000400448 T _init
0000000000400490 T _start
00000000004004bc t call_gmon_start
0000000000601020 b completed.7382
0000000000601010 W data_start
0000000000601028 b dtor_idx.7384
U [email protected]@GLIBC_2.2.5
0000000000400550 t frame_dummy
0000000000400574 T main

La mayoría de estos se refieren a funciones libc que se ejecutan antes y después de main para configurar el entorno. Puede ver que fmod ahora apunta a glibc, donde será resuelto por el sistema de biblioteca compartida.


Mi sistema está configurado para usar bibliotecas compartidas de forma predeterminada. Si, en cambio, fuerzo la vinculación estática, obtengo la dependencia de orden que ve


$ gcc -static -lm test.o
test.o: In function `main':
test.c:(.text+0x40): undefined reference to `fmod'
collect2: ld returned 1 exit status

Poniendo -lm más adelante en el comando del enlazador, después test.o , le permite vincularse con éxito.
La verificación de los símbolos fmod ahora debería resolverse en una dirección real, y de hecho lo es


$ gcc -static test.o -lm
$ nm a.out | grep fmod
0000000000400480 T __fmod
0000000000402b80 T __ieee754_fmod
0000000000400480 W fmod