C语言 对“仅某些 math.h”函数的未定义引用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6534191/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 09:02:58  来源:igfitidea点击:

undefined reference to "only some math.h" functions

cmathgccembeddednewlib

提问by theAlse

I am having a strange problem.

我有一个奇怪的问题。

The math libraries has been added to my makefile.

数学库已添加到我的 makefile 中。

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

and in the output file (.map) I can see that everything has been linked properly:

在输出文件 (.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

when I do

当我做

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

it works fine. But if I test another function like:

它工作正常。但是,如果我测试另一个功能,例如:

double result = asin(x);

I′ll get:

我去拿:

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

How can this be? both powand asinare available in math.h, see below:

怎么会这样?双方战俘阿辛是可用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) */

how can one work and the other one generate linker issue?If I run -nmon libm.aI′ll get the following result: (sorry for the huge output, I have only copied the sections with the word sin)

一个如何工作,另一个如何产生链接器问题?如果我在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

EDIT1:I tested some more and the problem is as follows (not what I originally stated above):

EDIT1:我测试了更多,问题如下(不是我上面最初所说的):

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

What happens when I try to build is that I get a 'undefined reference' at the last line, meaning that when I use constants it is fine, but when I pass variables to the sin functions it will not link. I also tested many of the other math function and I′ll get the exact same linker issue. As soon as I pass a variable to a math function I can not link any more. any ideas?

当我尝试构建时会发生什么,我在最后一行得到一个“未定义的引用”,这意味着当我使用常量时它很好,但是当我将变量传递给 sin 函数时,它不会链接。我还测试了许多其他数学函数,我会得到完全相同的链接器问题。一旦我将变量传递给数学函数,我就无法再链接了。有任何想法吗?

采纳答案by Keith Thompson

The linker isn't complaining about pow((double) 2, (double) 3)because the compiler is replacing it with a constant 8.0. You shouldn't depend on this behavior; instead, you should always use the -lmoption properly. (BTW, that's more clearly written as pow(2.0, 3.0).

链接器没有抱怨,pow((double) 2, (double) 3)因为编译器正在用一个常量替换它8.0。你不应该依赖这种行为;相反,您应该始终-lm正确使用该选项。(顺便说一句,这更清楚地写为pow(2.0, 3.0).

Consider the following program:

考虑以下程序:

#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;
}

When I compile and link it on my system using

当我使用以下命令在我的系统上编译和链接它时

gcc c.c -o c

I get:

我得到:

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

Note that it complains about asinbut not about pow.

请注意,它抱怨asin但不抱怨pow

If I change the powcall to pow(x, 3.0), I get:

如果我将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

Normally if you want to call a standard math library function, you need to have #include <math.h>at the top of the source file (I presume you already have that) andyou need to pass the -lmoption to the compiler afterthe file that needs it. (The linker keeps track of references that haven't been resolved yet, so it needs to see the object file that refers to asinfirst, so it can resolve it when it sees the math library.)

通常如果你想调用一个标准的数学库函数,你需要#include <math.h>在源文件的顶部(我假设你已经有了它)并且你需要在需要它的文件之后-lm选项传递给编译器。(链接器会跟踪尚未解析的引用,因此它需要查看首先引用的目标文件,以便在看到数学库时解析它。)asin

The linker isn't complaining about the call to pow(2.0, 3.0)because gcc is clever enough to resolve it to a constant 8.0. There's no call to the powfunction in the compiled object file, so the linker doesn't need to resolve it. If I change pow(2.0, 3.0)to pow(x, 3.0), the compiler doesn't know what the result is going to be, so it generates the call.

链接器不会抱怨对 的调用,pow(2.0, 3.0)因为 gcc 足够聪明,可以将其解析为常量8.0pow编译后的目标文件中没有调用该函数,因此链接器不需要解析它。如果我更改pow(2.0, 3.0)pow(x, 3.0),编译器不知道结果会是什么,所以它会生成调用。

回答by ottelo

The sequence for -lm -lc -lgccplays a very important role. Only this sequence works for me.

的序列-lm -lc -lgcc起着非常重要的作用。只有这个序列对我有用。

These commands go to the Linker Options!

这些命令转到链接器选项!

回答by Jonathan Leffler

Are you including <math.h>everywhere?

你包括<math.h>所有地方吗?

Notice that the names in the library are prefixed with __ieee754_, but the ones the linker can't find are not.

请注意,库中的名称以 为前缀__ieee754_,但链接器找不到的名称却没有。

What happens when you compile this code?

编译这段代码时会发生什么?

#include <math.h>

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

If the file is mathtest.c, then compile with:

如果文件是mathtest.c,则编译:

gcc -o mathtest mathtest.c -lm

(Given that this fails to compile, what symbols are defined in mathtest.o?)

(鉴于这无法编译,在 中定义了哪些符号mathtest.o?)



I added a comment to the main question:

我对主要问题添加了评论:

Which platform are you on? Which C compiler are you using? Are you cross-compiling? What is the command line that is executed to do the linking? (I see DOS/Windows C: paths and PowerPC architecture.) Is there any chance you are using for type-generic math?

你在哪个平台?您使用的是哪种 C 编译器?你是交叉编译吗?执行链接的命令行是什么?(我看到 DOS/Windows C: 路径和 PowerPC 体系结构。)您是否有机会用于类型通用数学?

Looking at the LOAD paths you give, I see:

查看您提供的 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/bin/../lib/gcc/powerpc-eabi/4.3.3/../../../../powerpc-eabi/lib/nof\libm.a

Which can, I think, be simplified to:

我认为可以简化为:

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

One part of that path that intrigues me is the nofpart; could that be 'no floating point'? The other part that really intrigues me is the presence of powerpcwith the c:prefix; it smacks of cross-compilation for PowerPC on a Windows platform. It is important to be forthright and explicit about such things; we need that sort of information to be able to help you sensibly.

这条道路中让我着迷的nof一部分是那部分;那可能是“无浮点”吗?另一部分,真正令我着迷是存在powerpcc:前缀; 它有点像在 Windows 平台上为 PowerPC 进行交叉编译。对这些事情坦率和明确是很重要的;我们需要这类信息才能明智地帮助您。

Was this the libm.alibrary that you tested, or did you experiment with another file?

libm.a是您测试的库,还是您试验了另一个文件?

回答by Mayank Kashyap

You can use "filename.c -lm" to solve this problem . And please don't forget to use header file math.h

您可以使用“filename.c -lm”来解决这个问题。并且请不要忘记使用头文件 math.h