2011-02-15 34 views
78

he el siguiente código (pelado abajo a los fundamentos pelados para esta pregunta):referencia indefinida a `sin`

#include<stdio.h> 
#include<math.h> 

double f1(double x) 
{ 
    double res = sin(x); 
    return 0; 
} 

/* The main function */ 
int main(void) 
{ 
    return 0; 
} 

Al compilar con gcc test.c me sale el siguiente error y no puedo trabajar por qué:

/tmp/ccOF5bis.o: In function `f1': 
test2.c:(.text+0x13): undefined reference to `sin' 
collect2: ld returned 1 exit status 

Sin embargo, he escrito varios programas de prueba que requieren sin dentro de la función main, y los que funcionan a la perfección. Debo estar haciendo algo obviamente mal aquí, pero ¿qué es?

+1

Creo que [esto podría ser un duplicado] (http://stackoverflow.com/q/4188409/300805) – peoro

+0

@ peoro, No me sorprendería. Esta es una biblioteca "olvidada" muy común. –

Respuesta

98

Ha compilado el código con referencias al archivo de cabecera math.h correcta, pero cuando se ha intentado vincularlo, se le olvidó la opción para incluir la biblioteca matemática. Como resultado, puede compilar sus archivos de objeto .o, pero no construir su ejecutable.

Como Paul ya ha mencionado, agregue "-lm" para vincular con la biblioteca de matemáticas en el paso donde está intentando generar su ejecutable.

En el comment, linuxD pregunta:

Por qué para sin() en <math.h>, qué necesitamos -lm opción explícita; pero, no para printf() en <stdio.h>?

Porque estas dos funciones se implementan como parte de la "Especificación única UNIX". Este historial de este estándar es interesante y se lo conoce por muchos nombres (IEEE Std 1003.1, X/Open Portability Guide, POSIX, Spec 1170).

Esta norma, specifically separates out the "Standard C library" routines from the "Standard C Mathematical Library" routines (page 277). El pasaje pertinente se copia a continuación:

biblioteca estándar de C

la biblioteca estándar de C se busca automáticamente por cc para resolver referencias externas. Esta biblioteca es compatible con todas las interfaces del Sistema base, tal como se define en el Volumen 1, a excepción de las Rutinas de Matemáticas .

biblioteca estándar de C Matemática

Esta biblioteca es compatible con las rutinas matemáticas sistema base, como se define en el Volumen 1. La opción cc -lm se utiliza para buscar esta biblioteca.

El razonamiento detrás de esta separación fue influenciado por una serie de factores:

  1. El UNIX wars llevado a una creciente divergencia entre el original en & oferta T UNIX.
  2. El número de plataformas UNIX agregó dificultad en el desarrollo de software para el sistema operativo.
  3. Se lanzó un intento de definir el mínimo común denominador para los desarrolladores de software, called 1988 POSIX.
  4. Desarrolladores de software programados según el estándar POSIX para proporcionar su software en "sistemas compatibles con POSIX" para alcanzar más plataformas.
  5. Los clientes de UNIX exigieron sistemas UNIX "compatibles con POSIX" para ejecutar el software.

Las presiones que se alimentaban en la decisión de poner -lm en una biblioteca diferente, probablemente, se incluye, pero no se limitan a:

  1. Parece una buena manera de mantener el tamaño de libc hacia abajo, como muchas aplicaciones no usan funciones integradas en la biblioteca matemática.
  2. Proporciona flexibilidad en la implementación de la biblioteca matemática, donde algunas bibliotecas matemáticas se basan en tablas de búsqueda integradas más grandes, mientras que otras pueden confiar en tablas de búsqueda más pequeñas (soluciones informáticas).
  3. Para aplicaciones realmente el tamaño limitados, permite reimplementaciones de la biblioteca matemática de una forma no estándar (como tirar hacia fuera apenas sin() y ponerlo en una biblioteca hecha a la medida.

En cualquier caso, es ahora parte del estándar para que no se incluya automáticamente como parte del lenguaje C, y es por eso que debe agregar -lm.

+3

por qué para sin (math.h), necesitamos la opción -lm explícitamente pero no para printf() fn definida en stdio.h, dudo sobre las capacidades del enlazador de GNU. Como en VCC, funciona y también en mac como se mencionó en flarn2006. – linuxD

+1

@KeithThompson Agregué mucho a la respuesta para matar el comentario. Disfrutar. –

+0

Tenga en cuenta que la biblioteca del sistema en una Mac (que ejecuta Mac OS X o macOS) incluye las funciones matemáticas. Hay una biblioteca para satisfacer las referencias a '-lm' en compilaciones, pero no es necesario usar' -lm' para vincular las funciones matemáticas. El principal problema que llevó a la separación de la biblioteca de matemáticas del resto fue que las CPU no siempre tenían incorporado un punto flotante; había coprocesadores de coma flotante (80387, etc.), y así sucesivamente, de modo que había muchas maneras de proporcionar la funcionalidad (usando bibliotecas de punto flotante de software o usando hardware con diferentes cantidades de soporte). –

35

Es necesario para enlazar con la biblioteca matemática, libm:

$ gcc -Wall foo.c -o foo -lm 
8

Tuve el mismo problema, que desapareció después de que enumeré mi biblioteca por última vez: gcc prog.c -lm

53

Tengo el problema de todos modos con -lm agregado

gcc -Wall -lm mtest.c -o mtest.o 
mtest.c: In function 'f1': 
mtest.c:6:12: warning: unused variable 'res' [-Wunused-variable] 
/tmp/cc925Nmf.o: In function `f1': 
mtest.c:(.text+0x19): undefined reference to `sin' 
collect2: ld returned 1 exit status 

Descubrí recientemente que no funciona si primero especifica -lm. Las cuestiones de orden:

gcc mtest.c -o mtest.o -lm 

ponga el enlace sin problemas

lo que debe especificar las bibliotecas después.

+0

Es un problema que ha estado molestando a gcc desde siempre :) ¡Pensé que cinco años y dos lanzamientos importantes lo habrían curado, en cambio, todavía está allí! Divertido :) –

+0

También tuve el mismo problema al demandar el último gcc 4.9 – Santi

+0

Feliz de informar que esto no ocurre con gcc 5.4 o gcc 6.2.1. – Pockets