未定义引用“仅一些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中提供了powasin ,见下文:

 /* 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