【问题标题】:Undefined reference to sqrt (or other mathematical functions)对 sqrt(或其他数学函数)的未定义引用
【发布时间】:2011-07-12 01:24:55
【问题描述】:

我有这个简单的代码:

max = (int) sqrt (number);

在标题中我有:

#include <math.h>

但应用程序仍然显示对sqrt 的未定义引用。你看到这里有什么问题吗?看起来一切都应该没问题。

【问题讨论】:

  • 哪个抱怨,链接器还是编译器?如果您可以发布可能会解决问题的确切错误。
  • 编译器写这个抱怨,问题是,那个应用甚至没有构建......
  • 问题不在于您的程序,而在于您系统的 C 库实现。它仍然遵循 1970 年代/1980 年代的传统约定,其中数学函数位于单独的库中,默认情况下未链接。

标签: c linker-errors undefined-reference


【解决方案1】:

你可能会发现你必须在你使用的任何系统上链接数学库,比如:

gcc -o myprog myprog.c -L/path/to/libs -lm
                                       ^^^ - this bit here.

包含标头可以让编译器了解函数声明,但它确实不一定会自动链接到执行该函数所需的代码。

否则,您需要向我们展示您的代码、编译命令和您正在运行的平台(操作系统、编译器等)。

以下代码可以正常编译和链接:

#include <math.h>
int main (void) {
    int max = sqrt (9);
    return 0;
}

请注意,一些编译系统依赖于在命令行中给出库的顺序。我的意思是,他们可以按顺序处理库,并且只使用它们来满足序列中那个点上未解析的符号

因此,例如,给定命令:

gcc -o plugh plugh.o -lxyzzy
gcc -o plugh -lxyzzy plugh.o

plugh.o 需要xyzzy 库中的某些内容,第二个可能无法按您的预期工作。在您列出库时,没有需要满足的未解析符号。

而当plugh.o中的未解析符号出现确实时,为时已晚。

【讨论】:

  • @paxdiablo : 对于 csqrt 的 µClibc
  • 还要注意链接库的顺序。我发现我在命令行中使用 -lm 太早了,将它移到最后可以解决相关的错误消息。这似乎也取决于 gcc 版本(一些旧版本并不那么介意)。
  • @Gabriel,我认为我的最后一部分(“请注意......”)涵盖了这一点。在任何情况下,它都不是必须排在最后的,它只是不能排在任何需要它的东西之前。我的意思是user_of_sin -lm user_of_cos user_of_xx -lprovider_of_xx 适用于除cos 之外的所有内容(假设sincos 是库中的单独 对象)。当然,最后可能是最安全的放置位置(假设它不需要任何东西)但我今天感觉很迂腐:-)
  • @paxdiablo,感谢您的澄清。是的,您的附加评论是迂腐正确的(意思是技术上正确),而我的评论是实际上正确(意思是:在实际意义上作为一般经验法则是正确的)。我想不出任何将所有库放在最后的情况是功能性的和你想要的,虽然,技术上,正如你所说,库只需要紧跟在需要它的目标文件或源文件之后。
  • @Gabriel,没有问题。我同意所有库都应该在所有对象之后。我之前已经被循环库依赖所烧毁,需要像-laaa -lbbb -laaa 这样的怪物来确保解决依赖关系。当库中的不同对象具有复杂的循环依赖关系时,我什至见过多次需要此往返的情况。我不知道为什么 GNU ld 至少不提供一个 option 来返回以前给定的库以满足新的未解析符号。
【解决方案2】:

我想你已经用#include &lt;math.h&gt; 导入了 math.h

所以我能看到的唯一其他原因是缺少链接信息。您必须使用 -lm 选项链接您的代码。

如果您只是想用 gcc 编译一个文件,只需在命令行中添加 -lm,否则,请提供一些有关您的构建过程的信息。

【讨论】:

    【解决方案3】:

    只需在 c 源文件中添加 #include &lt;math.h&gt;,最后在 Makefile 中添加 -lm 即可。

        gcc -pthread -o p3 p3.c -lm
    

    【讨论】:

      【解决方案4】:

      这是我的观察,首先您需要将标题 math.h 包含在 sqrt() 函数中声明在 math.h 头文件中。例如

      #include <math.h>
      

      其次,如果您阅读sqrt 的手册页,您会注意到这一行Link with -lm.

      #include <math.h> /* header file you need to include */
      
      double sqrt(double x); /* prototype of sqrt() function */
      
      Link with -lm. /* Library linking instruction */
      

      但是应用程序仍然说对 sqrt 的未定义引用。你有没有看到 这里有问题?

      编译器错误是正确的,因为您尚未将程序与库 lm 链接,并且链接器无法找到 sqrt() 的引用,您需要明确链接它。例如

      gcc -Wall -Wextra -Werror -pedantic test.c -lm
      

      【讨论】:

        【解决方案5】:

        我遇到了同样的问题,但我只是通过在运行我的代码的命令后添加 -lm 来解决它。 例子。 gcc code.c -lm

        【讨论】:

        • 这与几年前发布的其他答案有何不同?
        猜你喜欢
        • 1970-01-01
        • 2013-05-04
        • 2015-01-09
        • 1970-01-01
        • 2012-02-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多