在Ubuntu上,使用GCC和-lm链接不会定义ceil()函数

22

我目前正在使用GCC进行编译,并需要使用<math.h>库。

问题在于它无法识别该库。

我还尝试过-lm,但没有成功。

我尝试使用的函数是ceil(),并且我收到以下错误:

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

我正在使用最新的Ubuntu,math.h是存在的。 我曾在另一台计算机上使用 -lm,它完全可以工作。

我该如何解决这个问题?

我确实包含了 <math.h>。此外,我使用的命令是:

gcc -lm -o fb file.c

4
你能提供你正在使用的完整命令行吗? - Gian
我已经包含了math.h库文件。 另外,我使用的命令是: gcc -lm -o fb file.c - drum
11
你是否在源文件名后面指定了“-lm”? - Keith Thompson
4
在源文件名称后指定库名,就能解决你的问题。 - Jonathan Leffler
@JonathanLeffler 谢谢!没想到标志的顺序很重要。 - drum
显示剩余4条评论
3个回答

33

将这段代码复制到一个名为ceil.c的文件中:

#include <math.h>
#include <stdio.h>
int main(void)
{
    printf("%f\n", ceil(1.2));
    return 0;
}

使用以下命令进行编译:

$ gcc -o ceil ceil.c
$ gcc -o ceil ceil.c -lm
其中的任意一个应该都有效。如果都无效,那么请提供每个编译过程的完整错误信息。请注意,-lm 出现在源文件的名称之后(或者如果您将源代码编译为目标文件后再链接,则出现在目标文件之后)。
注: 1. 现代编译器可能会优化代码直接将2.0传递给 printf() 而不需要在运行时调用 ceil(),因此根本不需要数学库。 2. 经验法则:在命令行中按顺序列出对象文件和源文件后再列出库文件。本答案展示了使用方法:在源文件 ceil.c 之后出现了 -lm。 如果您使用 make 构建等构建工具,则通常会在命令行上使用 ceil.o(以及其他对象文件)。通常情况下,您应该在任何库文件之前列出所有对象文件。
经验法则有时候也有例外情况,但这种情况很少,并且应该对出现异常情况的特定案例进行记录。如果没有明确的相反说明文档,请遵循经验法则。

@Johnathan Leffler,编译时有没有不用每次都输入-lm的方法? - Brandon
@Brandon:迁移到Mac? <math.h> 中的函数在主系统库中,因此您不需要指定 -lm(尽管有一个 libm.dylib 可以为您提供一个库来链接,如果您在命令行上指定了 -lm)。否则,请确保您正在使用一个 makefile,并且如果您使用它足够多次,您已经设置了 LDLIBS(或 LDLIBES)为 -lm — 或编写每个程序所需的包含/排除库的特定规则。换句话说,“没有办法避免指定它”。您可以问GLibC团队为什么没有转向单一库。 - Jonathan Leffler
请注意,如果您优化代码,则编译器有可能在编译时评估ceil(1.2)并避免在运行时调用函数,这样您可能根本不需要-lm库。但对于我的示例程序来说,这将是一个模糊的边缘情况 - 一般情况下,编译器将无法进行该优化,然后您需要链接数学库,除非这些函数已经在主系统库中。 - Jonathan Leffler
谢谢!我忘了在文件后面加标志。 - Flipbed

12
我只想提一下Peter van der Linden的书《Expert C Programming》,其中第5章Thinking of Linking对这个主题有很好的处理。

归档文件(静态库)和共享对象(动态库)的操作方式不同。对于动态库,所有库符号都进入输出文件的虚拟地址空间,并且所有符号都可供链接中的其他文件使用。相比之下,静态链接仅在处理归档文件时查找当前加载器已知的未定义符号。

如果在你的目标文件之前指定数学库(通常是静态库),那么链接器将不会添加任何符号。


8

请尝试按照以下方式进行编译:

gcc -Wall -g file.c -lm -o file

我曾经遇到过同样的问题,使用以下命令解决了。另外,如果你在Ubuntu安装后的同一天遇到这个问题,可能是更新问题。


2
这个问题早已得到解答。 - drum
1
经验法则:源文件或目标文件之后再加库文件——这个命令行遵循这个经验法则。 - Jonathan Leffler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接