Неопределенная ссылка на "только некоторые math.h" функции
У меня странная проблема.
Математические библиотеки были добавлены в мой make-файл.
# include standard C library
LDFLAGS += -lc
# include standard math library
LDFLAGS += -lm
и в выходном файле (.map) я вижу, что все было правильно связано:
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
когда я делаю
z = pow((double) 2, (double) 3);
это работает отлично. Но если я проверю другую функцию, например:
double result = asin(x);
Я получу:
undefined reference to `asin'
collect2: ld returned 1 exit status
Как это может быть? и pow, и asin доступны в math.h, см. ниже:
/* 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) */
как один может работать, а другой генерирует проблему компоновщика? Если я запускаю -nm в libm.a, я получу следующий результат: (извините за огромный вывод, я скопировал только разделы со словом sin)
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
РЕДАКТИРОВАТЬ1: Я проверил еще несколько, и проблема заключается в следующем (не то, что я первоначально заявил выше):
double aa;
double bb = 1.0;
double cc;
aa = sin(1.0);
cc = sin (bb);
Когда я пытаюсь построить, происходит то, что в последней строке я получаю "неопределенную ссылку", что означает, что когда я использую константы, это нормально, но когда я передаю переменные в функции sin, они не будут связываться. Я также протестировал многие другие математические функции и получу точно такую же проблему с компоновщиком. Как только я передаю переменную в математическую функцию, я больше не могу связывать. есть идеи?
4 ответа
Линкер не жалуется на pow((double) 2, (double) 3)
потому что компилятор заменяет его константой 8.0
, Вы не должны зависеть от этого поведения; вместо этого вы всегда должны использовать -lm
вариант правильно. (Кстати, это более четко написано как pow(2.0, 3.0)
,
Рассмотрим следующую программу:
#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;
}
Когда я компилирую и связываю его в моей системе, используя
gcc c.c -o c
Я получил:
/tmp/ccXx8ZRL.o: In function `main':
c.c:(.text+0x36): undefined reference to `asin'
collect2: ld returned 1 exit status
Обратите внимание, что он жалуется на asin
но не о pow
,
Если я изменю pow
позвонить pow(x, 3.0)
, Я получил:
/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
Обычно, если вы хотите вызвать стандартную математическую библиотечную функцию, вам нужно иметь #include <math.h>
в верхней части исходного файла (я полагаю, у вас уже есть это), и вам нужно передать -lm
Опция для компилятора после файла, который нуждается в этом. (Компоновщик отслеживает ссылки, которые еще не были разрешены, поэтому он должен увидеть объектный файл, который ссылается на asin
во-первых, он может разрешить его, когда увидит математическую библиотеку.)
Линкер не жалуется на звонок pow(2.0, 3.0)
потому что gcc достаточно умен, чтобы разрешить его до константы 8.0
, Там нет вызова к pow
функция в скомпилированном объектном файле, поэтому компоновщик не должен ее разрешать. Если я изменю pow(2.0, 3.0)
в pow(x, 3.0)
компилятор не знает, каким будет результат, поэтому он генерирует вызов.
Последовательность для -lm -lc -lgcc
играет очень важную роль. Только эта последовательность работает для меня.
Эти команды идут в настройках компоновщика!
Вы в том числе <math.h>
везде?
Обратите внимание, что имена в библиотеке имеют префикс __ieee754_
, но те, что компоновщик не может найти, не являются.
Что происходит, когда вы компилируете этот код?
#include <math.h>
int main(void)
{
double d = pow(2, 3);
double e = asin(1.0 / d);
return (int)(e+1);
}
Если файл mathtest.c
, затем скомпилируйте с:
gcc -o mathtest mathtest.c -lm
(Учитывая, что это не скомпилировать, какие символы определены в mathtest.o
?)
Я добавил комментарий к основному вопросу:
На какой ты платформе? Какой компилятор C вы используете? Вы кросс-компилируете? Какая командная строка выполняется для связывания? (Я вижу DOS/Windows C: пути и архитектуру PowerPC.) Есть ли шанс, что вы используете для математики общего типа?
Глядя на пути загрузки, которые вы даете, я вижу:
LOAD c:/gnu/powerpc-eabi/3pp.ronetix.powerpc-eabi/bin/../lib/gcc/powerpc-eabi/4.3.3/../../../../powerpc-eabi/lib/nof\libm.a
Что, я думаю, может быть упрощено до:
LOAD c:/gnu/powerpc-eabi/3pp.ronetix.powerpc-eabi/powerpc-eabi/lib/nof\libm.a
Одна часть этого пути, которая меня интригует, это nof
часть; это может быть "без плавающей запятой"? Другая часть, которая действительно интригует меня, это присутствие powerpc
с c:
префикс; это попахивает кросс-компиляцией для PowerPC на платформе Windows. Важно быть прямым и откровенным о таких вещах; нам нужна такая информация, чтобы иметь возможность помочь вам разумно.
Это был libm.a
библиотека, которую вы тестировали, или вы экспериментировали с другим файлом?
Вы можете использовать "filename.c -lm" для решения этой проблемы. И, пожалуйста, не забудьте использовать заголовочный файл math.h