2011-06-30 20 views
8

Tengo un problema extraño.referencia indefinida a "solo algunas funciones math.h"

Las bibliotecas matemáticas se han agregado a mi archivo MAKE.

# include standard C library 
LDFLAGS += -lc 
# include standard math library 
LDFLAGS += -lm 

y en el archivo de salida (.map) puedo ver que todo lo que se ha vinculado correctamente:

LOAD c:/gnu/powerpc-eabi/3pp.ronetix.powerpc-eabi/bin/../lib/gcc/powerpc-eabi/4.3.3/nof\libgcc.a 
LOAD c:/gnu/powerpc-eabi/3pp.ronetix.powerpc-eabi/bin/../lib/gcc/powerpc-eabi/4.3.3/../../../../powerpc-eabi/lib/nof\libc.a 
LOAD c:/gnu/powerpc-eabi/3pp.ronetix.powerpc-eabi/bin/../lib/gcc/powerpc-eabi/4.3.3/../../../../powerpc-eabi/lib/nof\libm.a 

cuando lo haga

z = pow((double) 2, (double) 3); 

que trabaja muy bien. Pero si pruebo otra función como:

double result = asin(x); 

voy conseguir:

undefined reference to `asin' 
collect2: ld returned 1 exit status 

¿Cómo puede ser esto? tanto pow y asin están disponibles en math.h, ver más abajo:

/* Non reentrant ANSI C functions. */ 

#ifndef _REENT_ONLY 
#ifndef __math_6881 
extern double acos _PARAMS((double)); 
extern double asin _PARAMS((double)); 
extern double atan2 _PARAMS((double, double)); 
extern double cosh _PARAMS((double)); 
extern double sinh _PARAMS((double)); 
extern double exp _PARAMS((double)); 
extern double ldexp _PARAMS((double, int)); 
extern double log _PARAMS((double)); 
extern double log10 _PARAMS((double)); 
extern double pow _PARAMS((double, double)); 
extern double sqrt _PARAMS((double)); 
extern double fmod _PARAMS((double, double)); 
#endif /* ! defined (__math_68881) */ 
#endif /* ! defined (_REENT_ONLY) */ 

¿cómo se puede trabajar y el otro generar cuestión enlazador? Si me quedo -nm en libm.a voy obtener el siguiente resultado: (lo siento por la enorme producción, sólo han copiado las secciones con la palabra pecado )

lib_a-e_asin.o: 
     U __adddf3 
     U __divdf3 
     U __gtdf2 
00000000 T __ieee754_asin 
     U __ieee754_sqrt 
     U __muldf3 
     U __subdf3 
     U fabs 

lib_a-e_j0.o: 
     U __adddf3 
     U __divdf3 
     U __gtdf2 
00000470 T __ieee754_j0 
     U __ieee754_log 
     U __ieee754_sqrt 
000009b8 T __ieee754_y0 
     U __ltdf2 
     U __muldf3 
     U __subdf3 
     U cos 
     U fabs 
000000b0 r pR2 
00000108 r pR3 
00000058 r pR5 
00000000 r pR8 
000000e0 r pS2 
00000138 r pS3 
00000088 r pS5 
00000030 r pS8 
00000004 t pzero 
00000220 r qR2 
00000280 r qR3 
000001c0 r qR5 
00000160 r qR8 
00000250 r qS2 
000002b0 r qS3 
000001f0 r qS5 
00000190 r qS8 
00000218 t qzero 
     U sin 

lib_a-e_j1.o: 
     U __adddf3 
     U __divdf3 
     U __gtdf2 
00000470 T __ieee754_j1 
     U __ieee754_log 
     U __ieee754_sqrt 
00000950 T __ieee754_y1 
     U __muldf3 
     U __subdf3 
     U cos 
     U fabs 
00000004 t pone 
000000b0 r pr2 
00000108 r pr3 
00000058 r pr5 
00000000 r pr8 
000000e0 r ps2 
00000138 r ps3 
00000088 r ps5 
00000030 r ps8 
00000218 t qone 
00000220 r qr2 
00000280 r qr3 
000001c0 r qr5 
00000160 r qr8 
00000250 r qs2 
000002b0 r qs3 
000001f0 r qs5 
00000190 r qs8 
     U sin 

lib_a-e_jn.o: 
     U __adddf3 
     U __divdf3 
     U __floatsidf 
     U __gedf2 
     U __gtdf2 
     U __ieee754_j0 
     U __ieee754_j1 
00000434 T __ieee754_jn 
     U __ieee754_log 
     U __ieee754_sqrt 
     U __ieee754_y0 
     U __ieee754_y1 
00000000 T __ieee754_yn 
     U __ltdf2 
     U __muldf3 
     U __subdf3 
     U cos 
     U fabs 
     U sin 


lib_a-e_sinh.o: 
     U __adddf3 
     U __divdf3 
     U __gtdf2 
     U __ieee754_exp 
00000000 T __ieee754_sinh 
     U __muldf3 
     U __subdf3 
     U expm1 
     U fabs 


lib_a-ef_asin.o: 
     U __addsf3 
     U __divsf3 
     U __gtsf2 
00000000 T __ieee754_asinf 
     U __ieee754_sqrtf 
     U __mulsf3 
     U __subsf3 
     U fabsf 


lib_a-ef_j0.o: 
     U __addsf3 
     U __divsf3 
     U __gtsf2 
0000035c T __ieee754_j0f 
     U __ieee754_logf 
     U __ieee754_sqrtf 
000006cc T __ieee754_y0f 
     U __ltsf2 
     U __mulsf3 
     U __subsf3 
     U cosf 
     U fabsf 
00000058 r pR2 
00000084 r pR3 
0000002c r pR5 
00000000 r pR8 
00000070 r pS2 
0000009c r pS3 
00000044 r pS5 
00000018 r pS8 
00000004 t pzerof 
00000110 r qR2 
00000140 r qR3 
000000e0 r qR5 
000000b0 r qR8 
00000128 r qS2 
00000158 r qS3 
000000f8 r qS5 
000000c8 r qS8 
000001a0 t qzerof 
     U sinf 

lib_a-ef_j1.o: 
     U __addsf3 
     U __divsf3 
     U __gtsf2 
0000031c T __ieee754_j1f 
     U __ieee754_logf 
     U __ieee754_sqrtf 
0000062c T __ieee754_y1f 
     U __mulsf3 
     U __subsf3 
     U cosf 
     U fabsf 
00000004 t ponef 
00000058 r pr2 
00000084 r pr3 
0000002c r pr5 
00000000 r pr8 
00000070 r ps2 
0000009c r ps3 
00000044 r ps5 
00000018 r ps8 
000001a0 t qonef 
000000b0 r qr2 
000000e0 r qr8 
000000c8 r qs2 
000000f8 r qs8 
     U sinf 

lib_a-ef_sinh.o: 
     U __addsf3 
     U __divsf3 
     U __gtsf2 
     U __ieee754_expf 
00000000 T __ieee754_sinhf 
     U __mulsf3 
     U __subsf3 
     U expm1f 
     U fabsf 

lib_a-er_lgamma.o: 
     U __adddf3 
     U __divdf3 
     U __eqdf2 
     U __fixdfsi 
     U __floatsidf 
00000004 T __ieee754_lgamma_r 
     U __ieee754_log 
     U __kernel_cos 
     U __kernel_sin 
     U __ltdf2 
     U __muldf3 
     U __nedf2 
     U __subdf3 
     U fabs 
     U floor 


lib_a-erf_lgamma.o: 
     U __addsf3 
     U __divsf3 
     U __eqsf2 
     U __fixsfsi 
     U __floatsisf 
00000004 T __ieee754_lgammaf_r 
     U __ieee754_logf 
     U __kernel_cosf 
     U __kernel_sinf 
     U __ltsf2 
     U __mulsf3 
     U __nesf2 
     U __subsf3 
     U fabsf 
     U floorf 

lib_a-k_sin.o: 
     U __adddf3 
     U __fixdfsi 
00000000 T __kernel_sin 
     U __muldf3 
     U __subdf3 

lib_a-kf_sin.o: 
     U __addsf3 
     U __fixsfsi 
00000000 T __kernel_sinf 
     U __mulsf3 
     U __subsf3 

lib_a-s_asinh.o: 
     U __adddf3 
     U __divdf3 
     U __gtdf2 
     U __ieee754_log 
     U __ieee754_sqrt 
     U __muldf3 
00000000 T asinh 
     U fabs 
     U log1p 

lib_a-s_cos.o: 
     U __ieee754_rem_pio2 
     U __kernel_cos 
     U __kernel_sin 
     U __subdf3 
00000000 T cos 

lib_a-s_isinf.o: 
00000000 T isinf 

lib_a-s_isinfd.o: 
00000000 T __isinfd 

lib_a-s_sin.o: 
     U __ieee754_rem_pio2 
     U __kernel_cos 
     U __kernel_sin 
     U __subdf3 
00000000 T sin 

lib_a-sf_asinh.o: 
     U __addsf3 
     U __divsf3 
     U __gtsf2 
     U __ieee754_logf 
     U __ieee754_sqrtf 
     U __mulsf3 
00000000 T asinhf 
     U fabsf 
     U log1pf 

lib_a-sf_cos.o: 
     U __ieee754_rem_pio2f 
     U __kernel_cosf 
     U __kernel_sinf 
     U __subsf3 
00000000 T cosf 

lib_a-sf_isinf.o: 
00000000 T isinff 

lib_a-sf_isinff.o: 
00000000 T __isinff 

lib_a-sf_sin.o: 
     U __ieee754_rem_pio2f 
     U __kernel_cosf 
     U __kernel_sinf 
     U __subsf3 
00000000 T sinf 

lib_a-w_asin.o: 
     U __errno 
     U __fdlib_version 
     U __gtdf2 
     U __ieee754_asin 
     U __isnand 
00000004 T asin 
     U fabs 
     U matherr 
     U nan 

lib_a-w_sincos.o: 
     U cos 
     U sin 
00000000 T sincos 

lib_a-w_sinh.o: 
     U __errno 
     U __fdlib_version 
     U __gtdf2 
     U __ieee754_sinh 
     U finite 
     U matherr 
00000004 T sinh 

lib_a-wf_asin.o: 
     U __errno 
     U __extendsfdf2 
     U __fdlib_version 
     U __gtsf2 
     U __ieee754_asinf 
     U __truncdfsf2 
00000004 T asinf 
     U fabsf 
     U isnanf 
     U matherr 
     U nan 

lib_a-wf_sincos.o: 
     U cosf 
00000000 T sincosf 
     U sinf 

lib_a-wf_sinh.o: 
     U __errno 
     U __extendsfdf2 
     U __fdlib_version 
     U __gtsf2 
     U __ieee754_sinhf 
     U __truncdfsf2 
     U finitef 
     U matherr 
00000004 T sinhf 

EDIT1: que probé un poco más y el problema es el siguiente (no es lo que originalmente dicho anteriormente):

double aa; 
double bb = 1.0; 
double cc; 
aa = sin(1.0); 
cc = sin (bb); 

Lo que sucede cuando trato de compilar es que obtengo una referencia indefinida en la última línea, lo que significa que cuando uso constantes está bien, pero cuando paso variables a las funciones sin no se enlazará . También probé muchas de las otras funciones de matemáticas y obtendré exactamente el mismo problema de engarce. Tan pronto como paso una variable a una función matemática, ya no puedo vincular. ¿algunas ideas?

+0

son las llamadas a función en el mismo archivo? – Heisenbug

+2

Si usa la herramienta de su plataforma para listar la tabla de símbolos para un archivo de objeto (por ejemplo, ['nm'] (http://unixhelp.ed.ac.uk/CGI/man-cgi?nm)), son las funciones que faltan listado en libm.a? El error indica que el problema está en la fase de enlace, en cuyo momento los archivos de encabezado ya no están involucrados. En otras palabras, el contenido de math.h no afectará el problema. – outis

+0

sí, pow y asin están uno detrás de otro (salté la declaración de variable anterior) – theAlse

Respuesta

5

El enlazador no se queja de pow((double) 2, (double) 3) porque el compilador lo está reemplazando por una constante 8.0. No deberías depender de este comportamiento; en su lugar, siempre debe usar la opción -lm correctamente. . (Por cierto, eso es más claramente escrito como pow(2.0, 3.0)

Considere el siguiente programa:

#include <stdio.h> 
#include <math.h> 
int main(void) { 
    double x = 0.1; 
    printf("%g\n", pow(2.0, 3.0)); 
    printf("%g\n", asin(x)); 
    return 0; 
} 

Cuando compilación y enlace en mi sistema usando

gcc c.c -o c 

me sale:

/tmp/ccXx8ZRL.o: In function `main': 
c.c:(.text+0x36): undefined reference to `asin' 
collect2: ld returned 1 exit status 

Tenga en cuenta que se queja de asin pero no de pow.

Si cambio la llamada pow a pow(x, 3.0), me sale:

/tmp/ccOeSaBK.o: In function `main': 
c.c:(.text+0x24): undefined reference to `pow' 
c.c:(.text+0x52): undefined reference to `asin' 
collect2: ld returned 1 exit status 

Normalmente, si desea llamar a una función de biblioteca matemática estándar, es necesario tener #include <math.h> en la parte superior del archivo de origen (presumo ya lo tiene) y debe pasar la opción -lm al compilador después de el archivo que lo necesita.(El enlazador realiza un seguimiento de las referencias que aún no se han resuelto, por lo que primero necesita ver el archivo de objeto que hace referencia a asin, para que pueda resolverlo cuando vea la biblioteca matemática).

El vinculador no es quejándose de la llamada al pow(2.0, 3.0) porque gcc es lo suficientemente inteligente como para resolverlo en una constante 8.0. No hay llamadas a la función pow en el archivo de objeto compilado, por lo que el vinculador no necesita resolverlo. Si cambio pow(2.0, 3.0) a pow(x, 3.0), el compilador no sabe cuál será el resultado, por lo que genera la llamada.

7

¿Está incluyendo <math.h> en todos lados?

Observe que los nombres en la biblioteca tienen el prefijo __ieee754_, pero los que el vinculador no puede encontrar no lo están.

¿Qué ocurre cuando compila este código?

#include <math.h> 

int main(void) 
{ 
    double d = pow(2, 3); 
    double e = asin(1.0/d); 
    return (int)(e+1); 
} 

Si el archivo es mathtest.c, a continuación, compilar con:

gcc -o mathtest mathtest.c -lm 

(Dado que esta falla al compilar, qué símbolos se definen en mathtest.o?)


que añadió un comentario a la pregunta principal:

Qué plataforma está usted? ¿Qué compilador de C estás usando? ¿Estás haciendo una compilación cruzada? ¿Cuál es la línea de comando que se ejecuta para hacer el enlace? (Veo DOS/Windows C: rutas y arquitectura PowerPC.) ¿Hay alguna posibilidad de que esté utilizando matemáticas de tipo genérico?

En cuanto a las rutas de carga que facilite, que veo:

LOAD c:/gnu/powerpc-eabi/3pp.ronetix.powerpc-eabi/bin/../lib/gcc/powerpc-eabi/4.3.3/../../../../powerpc-eabi/lib/nof\libm.a 

que puede, pienso, puede simplificar a:

LOAD c:/gnu/powerpc-eabi/3pp.ronetix.powerpc-eabi/powerpc-eabi/lib/nof\libm.a 

Uno parte de ese camino que me intriga es el nof parte; ¿Podría ser eso 'no punto flotante'? La otra parte que realmente me intriga es la presencia de powerpc con el prefijo c:; huele a compilación cruzada para PowerPC en una plataforma de Windows. Es importante ser franco y explícito sobre tales cosas; necesitamos ese tipo de información para poder ayudarlo con sensatez.

¿Esta es la biblioteca libm.a que ha probado o ha experimentado con otro archivo?

+1

"Referencia no definida" es un error de enlazador, no un error del compilador, no incluir un archivo de encabezado provocaría un error de complemento (o una advertencia en C89). – Clifford

+5

@Clifford: a menos que la cabecera incluya el nombre del código fuente de 'asin' a' __ieee574_asin'. La salida de 'nm' muestra un símbolo' __ieee574_asin', y si el encabezado asigna el nombre como se sugiere, llamar a la función sin el encabezado significaría que se llamó a la función 'incorrecta'. Si el código de muestra que proporcioné tiene enlaces pero el código del póster original no, me inclinaría a considerarlo como "caso probado". Sí, legítimamente puedes argumentar que se supone que puedes escribir 'extern double asin (double);' y debería funcionar, pero he visto este tipo de mapeo de nombres antes. –

+0

@Jonathan: buen trabajo. –

6

La secuencia para -lm -lc -lgcc juega un papel muy importante. Solo esta secuencia funciona para mí.

¡Estos comandos van a las Opciones de Enlazador!

+1

Las opciones '-lc' y' lgcc' no son normalmente necesarias. ¿Qué entorno los requiere? –

0

Puede usar "filename.c -lm" para resolver este problema. Y por favor, no se olvide de utilizar el archivo de encabezado math.h