未定义对“ pow”和“ floor”的引用


124

我试图用C语言制作一个简单的斐波那契计算器,但是编译时gcc告诉我我缺少pow和floor函数。怎么了?

码:

#include <stdio.h>
#include <math.h>

int fibo(int n);

int main() {
        printf("Fib(4) = %d", fibo(4));
        return 0;
}

int fibo(int n) {
        double phi = 1.61803399;

        return (int)(floor((float)(pow(phi, n) / sqrt(5)) + .5f));
}

输出:

gab@testvm:~/work/c/fibo$ gcc fib.c -o fibo
/tmp/ccNSjm4q.o: In function `fibo':
fib.c:(.text+0x4a): undefined reference to `pow'
fib.c:(.text+0x68): undefined reference to `floor'
collect2: ld returned 1 exit status

由于浮点精度不是无限的,因此对于不那么大的值,这将给出错误的答案n
vonbrand 2013年


似乎存在一个更简单的解决方案,只需使用g ++代替:g ++ fib.c -o
fibo

Answers:


242

您需要使用link标志进行编译-lm,如下所示:

gcc fib.c -lm -o fibo

这将告诉gcc将您的代码链接到数学库。只要确保将标记放在要链接的对象之后即可。


7
您能解释一下如何写出-l后的字母吗?
加布里埃里·西鲁里

48
查看/ lib或/ usr / lib。这些库全都被命名为lib<name>.alib<name>.so-它是您在-l。之后加上的“ <name>” 。在这种情况下,数学库被命名为libm.so,因此我们将其称为-lm
AMS

3
谢谢!在过去的30分钟里,我一直在谷歌上搜索,这是第一个在对象之后链接库的
参考资料

您还可以使用LD_PRELOAD告诉ld运行时链接程序在进程的内存映射和符号表中包含libm.so,这样就可以加载这些符号,并且一切都按预期工作
首次亮相

感谢你的回答。但是有人可以告诉我为什么在几行代码的情况下即使我在编译时不包含-lm也可以吗?
MItrajyoti Kusari


9

为了以后阅读此书的人的利益,您需要像Fred所说的那样链接它:

gcc fib.c -lm -o fibo

找出需要链接的库的一种好方法是检查手册页(如果存在)。例如,man pow并且man floor都会告诉您:

与链接-lm

C语言程序中链接数学库的说明-C语言中的链接


8

关于模糊提供的答案:

我实际上不得不做些不同的事情。

项目->属性-> C / C ++构建->设置-> GCC C链接器->库

单击绿色的小添加图标,键入m并单击确定。由于它是一个库,因此该窗口中的所有内容都会自动应用-l。


6

找到在Eclipse-IDE中添加-lm的地步确实很可怕,所以花了我一些时间。

如果其他人也使用Edlipse,请按照以下方法添加命令:

项目->属性-> C / C ++构建->设置-> GCC C链接器->其他->链接器标志:在此字段中添加命令-lm


0

上面的所有答案都不完整,这里的问题出在链接器ld而不是编译器collect2: ld returned 1 exit status。在编译fib.c对象时:

$ gcc -c fib.c
$ nm fib.o
0000000000000028 T fibo
                 U floor
                 U _GLOBAL_OFFSET_TABLE_
0000000000000000 T main
                 U pow
                 U printf

其中nm列出了目标文件中的符号。您可以看到它已编译且没有错误,但是powfloorprintf函数具有未定义的引用,现在,如果我尝试将其链接到可执行文件:

$ gcc fib.o
fib.o: In function `fibo':
fib.c:(.text+0x57): undefined reference to `pow'
fib.c:(.text+0x84): undefined reference to `floor'
collect2: error: ld returned 1 exit status

我得到的输出类似。为了解决这个问题,我需要告诉链接器在哪里寻找对和的引用powfloor为此,我将使用来自库的链接器-l标志。mlibm.so

$ gcc fib.o -lm
$ nm a.out
0000000000201010 B __bss_start
0000000000201010 b completed.7697
                 w __cxa_finalize@@GLIBC_2.2.5
0000000000201000 D __data_start
0000000000201000 W data_start
0000000000000620 t deregister_tm_clones
00000000000006b0 t __do_global_dtors_aux
0000000000200da0 t 
__do_global_dtors_aux_fini_array_entry
0000000000201008 D __dso_handle
0000000000200da8 d _DYNAMIC
0000000000201010 D _edata
0000000000201018 B _end
0000000000000722 T fibo
0000000000000804 T _fini
                 U floor@@GLIBC_2.2.5
00000000000006f0 t frame_dummy
0000000000200d98 t __frame_dummy_init_array_entry
00000000000009a4 r __FRAME_END__
0000000000200fa8 d _GLOBAL_OFFSET_TABLE_
                 w __gmon_start__
000000000000083c r __GNU_EH_FRAME_HDR
0000000000000588 T _init
0000000000200da0 t __init_array_end
0000000000200d98 t __init_array_start
0000000000000810 R _IO_stdin_used
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
0000000000000800 T __libc_csu_fini
0000000000000790 T __libc_csu_init
                 U __libc_start_main@@GLIBC_2.2.5
00000000000006fa T main
                 U pow@@GLIBC_2.2.5
                 U printf@@GLIBC_2.2.5
0000000000000660 t register_tm_clones
00000000000005f0 T _start
0000000000201010 D __TMC_END__

您现在可以看到,功能powfloor链接到GLIBC_2.2.5

参数顺序也很重要,除非默认情况下将您的系统配置为使用共享库,否则我的系统就不会如此,因此在发出以下命令时:

$ gcc -lm fib.o
fib.o: In function `fibo':
fib.c:(.text+0x57): undefined reference to `pow'
fib.c:(.text+0x84): undefined reference to `floor'
collect2: error: ld returned 1 exit status

-lm对象文件之前的注释标志。因此,总而言之,请-lm确保在所有其他标志和参数之后添加标志。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.