【问题标题】:Undefined reference to `pow' and `floor'未定义对“pow”和“floor”的引用
【发布时间】:2012-01-30 01:52:54
【问题描述】:

我正在尝试用 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

【问题讨论】:

标签: c gcc undefined-reference


【解决方案1】:

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

gcc fib.c -lm -o fibo

这将告诉 gcc 将您的代码链接到数学库。请务必将标志置于您要链接的对象之后。

【讨论】:

  • 你能解释一下如何计算出放在-l之后的字母吗?
  • 查看 /lib 或 /usr/lib。这些库都被命名为lib&lt;name&gt;.alib&lt;name&gt;.so - 这是您在-l 之后放置的“”。在这种情况下,数学库被命名为libm.so,所以我们称之为-lm
  • 谢谢!过去 30 分钟我一直在谷歌搜索,这是第一个提到在对象之后链接库的参考
  • 您还可以使用 LD_PRELOAD 告诉 ld 运行时链接器将 libm.so 包含在进程的内存映射和符号表中,以便加载这些符号并且一切都按预期工作
  • 感谢您的回答。但是谁能告诉我为什么在代码只有几行的情况下即使我在编译时不包含 -lm 也没关系?
【解决方案2】:

将 -lm 添加到您的链接选项中,因为 pow() 和 floor() 是数学库的一部分:

gcc fib.c -o fibo -lm

【讨论】:

    【解决方案3】:

    为了以后阅读本文的人的利益,您需要按照 Fred 所说的链接它:

    gcc fib.c -lm -o fibo
    

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

    链接到-lm

    在C编程中链接数学库的解释-Linking in C

    【讨论】:

      【解决方案4】:

      关于 Fuzzy 提供的答案:

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

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

      点击绿色的小添加图标,输入 m 并点击确定。这个窗口中的所有内容都自动应用了 -l,因为它是一个库。

      【讨论】:

        【解决方案5】:

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

        如果其他人也使用 Edlipse,这里是添加命令的方法:

        Project -> Properties -> C/C++ Build -> Settings -> GCC C Linker -> Miscellaneous -> Linker flags:在此字段中添加命令 -lm

        【讨论】:

          【解决方案6】:

          以上所有答案都不完整,这里的问题在于链接器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 标志和m,它来自libm.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 标志,以确保。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2022-11-02
            • 1970-01-01
            • 2021-09-22
            • 2013-04-27
            • 1970-01-01
            • 1970-01-01
            • 2021-09-15
            相关资源
            最近更新 更多