未定义引用“仅一些math.h”函数
我有一个奇怪的问题。
数学库已添加到我的makefile中。
# 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
怎么会这样? math.h中提供了pow和asin ,见下文:
/* 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) */
如何工作,另一个生成链接器问题? 如果我在libm.a上运行-nm ,我将得到以下结果:(对于巨大的输出,我只复制了带有单词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函数时它不会链接。 我还测试了许多其他数学函数,我将得到完全相同的链接器问题。 一旦我将变量传递给数学函数,我就不能再连接了。 有任何想法吗?
链接器并没有抱怨pow((double) 2, (double) 3)
因为编译器正在用常量8.0
替换它。 你不应该依赖这种行为; 相反,您应该始终正确使用-lm
选项。 (顺便说一下,这更清楚地写成了pow(2.0, 3.0)
。
考虑以下程序:
#include #include int main(void) { double x = 0.1; printf("%g\n", pow(2.0, 3.0)); printf("%g\n", asin(x)); return 0; }
当我在我的系统上编译和链接时使用
gcc cc -oc
我明白了:
/tmp/ccXx8ZRL.o: In function `main': cc:(.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': cc:(.text+0x24): undefined reference to `pow' cc:(.text+0x52): undefined reference to `asin' collect2: ld returned 1 exit status
通常,如果你想调用一个标准的数学库函数,你需要在源文件的顶部有#include
(我假设你已经有了) ,你需要将-lm
选项传递给编译器在需要它的文件之后 。 (链接器会跟踪尚未解析的引用,因此需要先查看引用asin
的目标文件,以便在看到数学库时解析它。)
链接器并没有抱怨对pow(2.0, 3.0)
的调用pow(2.0, 3.0)
因为gcc足够聪明,可以将它解析为常量8.0
。 在编译的目标文件中没有调用pow
函数,因此链接器不需要解析它。 如果我将pow(2.0, 3.0)
更改为pow(x, 3.0)
,编译器将不知道结果是什么,因此它会生成调用。
你到处都包括
吗?
请注意,库中的名称以__ieee754_
为前缀,但链接器找不到的名称不是。
编译此代码时会发生什么?
#include 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架构。)你有没有机会使用类型generics数学?
看看你给出的LOAD路径,我看到:
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
部分; 那可能是“没有浮点”吗? 真正引起我兴趣的另一部分是带有c:
前缀的powerpc
; 它在Windows平台上为PowerPC进行交叉编译。 关于这些事情要坦率直言是非常重要的; 我们需要那种信息才能合理地帮助你。
这是您测试过的libm.a
库,还是您尝试过另一个文件?
-lm -lc -lgcc
的序列起着非常重要的作用。 只有这个序列对我有用。
这些命令转到链接器选项!
您可以使用“filename.c -lm”来解决此问题。 请不要忘记使用头文件math.h