未定义对“sin”的引用 [重复]

Undefined reference to `sin` [duplicate]

提问人:robintw 提问时间:2/15/2011 最后编辑:alkrobintw 更新时间:3/14/2022 访问量:177967

问:

我有以下代码(精简为这个问题的基本知识):

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

double f1(double x)
{
    double res = sin(x);
    return 0;
}

/* The main function */
int main(void)
{
    return 0;
}

编译时,我收到以下错误,我无法找出原因:gcc test.c

/tmp/ccOF5bis.o: In function `f1':
test2.c:(.text+0x13): undefined reference to `sin'
collect2: ld returned 1 exit status

但是,我编写了各种从函数内部调用的测试程序,这些程序运行良好。我一定在这里做错了什么——但它是什么?sinmain

c 数学 链接器错误 未定义引用

评论

1赞 peoro 2/15/2011
我认为这可能是重复的
0赞 Edwin Buck 2/15/2011
@peoro,这并不让我感到惊讶。这是一个非常常见的“被遗忘”的库。

答:

42赞 Paul R 2/15/2011 #1

您需要与数学库 libm 链接:

$ gcc -Wall foo.c -o foo -lm 
150赞 Edwin Buck 2/15/2011 #2

您已经使用对正确 math.h 头文件的引用编译了代码,但是当您尝试链接它时,您忘记了包含数学库的选项。因此,您可以编译 .o 对象文件,但不能生成可执行文件。

正如 Paul 已经提到的,在尝试生成可执行文件的步骤中添加 “” 以链接到数学库。-lm

评论中,linuxD 问道:

为什么 for in ,我们明确需要 option;但 不是为了在?sin()<math.h>-lmprintf()<stdio.h>

因为这两个功能都是作为“单一 UNIX 规范”的一部分实现的。这个标准的历史很有趣,并且有很多名字(IEEE Std 1003.1,X/Open Portability Guide,POSIX,Spec 1170)。

该标准专门将“标准 C 库”例程与“标准 C 数学库”例程分开(第 277 页)。相关段落抄录如下:

标准 C 库

标准 C 库会自动搜索以解析外部引用。该库支持所有 基本系统的接口,如第 1 卷中所定义,但 数学例程。cc

标准 C 数学库

该库支持 第 1 卷中定义的基本系统数学例程。该选项用于搜索此库。cc-lm

这种分离背后的原因受到许多因素的影响:

  1. UNIX战争导致与最初的AT&T UNIX产品越来越不同。
  2. UNIX 平台的数量增加了为操作系统开发软件的难度。
  3. 1988 年,为软件开发人员定义最低公分母的尝试开始了,称为 POSIX
  4. 软件开发人员根据POSIX标准进行编程,在“POSIX兼容系统”上提供他们的软件,以便覆盖更多平台。
  5. UNIX 客户需要“符合 POSIX 标准”的 UNIX 系统来运行该软件。

决定放入不同库的压力可能包括但不限于:-lm

  1. 这似乎是减小 libc 大小的好方法,因为许多应用程序不使用嵌入在数学库中的函数。
  2. 它为数学库实现提供了灵活性,其中某些数学库依赖于较大的嵌入式查找表,而其他数学库可能依赖于较小的查找表(计算解决方案)。
  3. 对于真正大小受限的应用程序,它允许以非标准方式重新实现数学库(例如仅将其拉出并将其放入自定义构建的库中)。sin()

无论如何,它现在是标准的一部分,不会自动包含在 C 语言中,这就是为什么您必须添加 .-lm

评论

4赞 linuxD 3/21/2013
为什么对于 sin (math.h),我们需要显式的 -lm 选项,但对于 stdio.h 中定义的 printf() fn 则不需要,我怀疑 GNU 的链接器功能。正如 flarn2006 所提到的,它在 VCC 中工作,在 mac 上也是如此。
2赞 Edwin Buck 7/12/2017
@KeithThompson 在答案中添加了很多内容以杀死评论。享受。
0赞 Jonathan Leffler 8/27/2017
请注意,Mac(运行 Mac OS X 或 macOS)上的系统库包含数学函数。有一个库可以满足构建中的引用,但您不需要使用它来链接数学函数。导致数学库与其他库分离的主要问题是 CPU 并不总是内置浮点数;有浮点协处理器(80387 等)等,因此有很多方法可以提供功能(使用软件浮点库,或使用具有不同支持量的硬件)。-lm-lm
0赞 Jonathan Leffler 8/27/2017
另请注意,c99 的现代 POSIX 规范“扩展描述——标准库”对库的指定略有不同——指出(作为许多其他库之一)的内容可以链接,而不一定需要在链接命令行上明确提及。答案中的引文来自 SVID 第 4 版(日期为 1995 年 7 月)。它与历史相关,但不再是决定性的。-lm
13赞 blackappy 1/13/2012 #3

我遇到了同样的问题,在我最后列出我的库后就消失了:gcc prog.c -lm

87赞 Anyeos 8/29/2012 #4

我仍然有添加的问题:-lm

gcc -Wall -lm mtest.c -o mtest.o
mtest.c: In function 'f1':
mtest.c:6:12: warning: unused variable 'res' [-Wunused-variable]
/tmp/cc925Nmf.o: In function `f1':
mtest.c:(.text+0x19): undefined reference to `sin'
collect2: ld returned 1 exit status

我最近发现,如果你先指定,它是行不通的。顺序很重要。您必须指定 last,如下所示:-lm-lm

gcc mtest.c -o mtest.o -lm

这链接没有问题。

因此,您必须在末尾指定库。

评论

1赞 Lorenzo Dematté 11/14/2013
这是一个自古以来就一直困扰着gcc的问题:)虽然五年和 2 个主要版本会治愈它,但它仍然存在!有趣的:)
0赞 Santiago 9/12/2015
我在起诉最新的 gcc 4.9 时也遇到了同样的问题
0赞 Pockets 1/13/2017
很高兴地报告,gcc 5.4 或 gcc 6.2.1 不会发生这种情况。
1赞 Jonathan Leffler 8/27/2017
始终在对象文件之后链接库。这总是有效的。在对象文件之前链接库有时有效,有时无效。(偶尔会有例外,但很少遇到,你会知道什么时候是相关的,该怎么做,因为你正在使用的图书馆的手册会告诉你,或者因为你写了手册。
0赞 Gabriel Staples 3/14/2022
谢谢你的回答!这个顺序问题仍然存在于。这失败了:,但这通过:。这也通过:。gcc --versiongcc (Ubuntu 8.4.0-1ubuntu1~18.04) 8.4.0gcc -lm -Wall -Wextra -Werror -O3 -std=c17 math_sin_is_undefined.c -o bin/agcc -Wall -Wextra -Werror -O3 -std=c17 math_sin_is_undefined.c -o bin/a -lmgcc -Wall -Wextra -Werror -O3 -std=c17 math_sin_is_undefined.c -lm -o bin/a