C语言 - 即使使用'-lm'仍出现“sqrt”未定义引用

11

我试图编译一个需要使用"math.h"的C库,这里是.c文件的开头:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h> 
#include "sparse_matrix.h"
...

我用这个命令进行编译:

gcc -c ./sparse_matrix.c -o sparse_matrix.o -lm -Wall -pedantic -std=c99 -g -O

尽管我已经使用了#include并在文件后面加上了标志-lm(我试过把它放在行尾但没有改变),但我仍然得到以下错误:undefined reference to « sqrt » collect2: error: ld returned 1 exit status

经过一小时的谷歌搜索,我还是不明白问题出在哪里。 我正在Ubuntu 14.10 (utopic unicorn)下使用gcc 4.9。 非常感谢您提前的任何帮助!


“-c”选项可以抑制链接。您不会从该命令行收到该错误。因此,那不是产生错误的命令行。(在makefile中不要在规则之前使用@ - 这可能不是您的问题,但它会隐藏命令并误导您。)而且大部分内容都是@paxdiablo所说的。 - Jonathan Leffler
可能是重复的问题:即使包含了math.h头文件并链接了-lm库,仍然出现“undefined reference to 'pow'”错误。请参考此链接:https://dev59.com/PWQo5IYBdhLWcg3wE78J - Ciro Santilli OurBigBook.com
1个回答

13

我认为你运行的不是那个命令(也许是其中之一,但肯定不是导致错误的命令)。

gcc-c 选项只会创建目标文件(你明确将输出发送到了一个目标文件 sparse_matrix.o,而不是可执行文件)。

在这种情况下,链接器根本不应该被调用。

实际上,使用一个虚拟的 sparse_matrix.c 文件:

#include <math.h>
int main(void) {
    return (int)(sqrt(16.0));
}

你的命令很好用,当我完成这个过程时会用到:

pax> gcc -o sparse_matrix sparse_matrix.o -lm
pax> ./sparse_matrix
pax> echo $?
4

您可以看到它也运行得很好。

可能是您在实际的 链接 阶段中缺少链接器标志(例如 -lm),这会导致此问题。 它们对编译阶段应该没有影响(除非它们影响编译和链接阶段,但 -l 不是这些选项之一)。

而 “遗漏” 还包括 “错放”的可能性。一些链接器在处理库时具有位置依赖性,只有在列出它们的未定义符号点满足时,它们才会从库中提取对象。

因此,命令为:

linker sparse_matrix.o -lm ...

如果您的链接器是非定位性的,那么 .o 文件可以正常工作,因为它引入了对 sqrt 的未满足引用,而这个引用可以被 libm 满足。如果您的链接器是定位性的,则:

linker -lm sparse_matrix.o ...

因为在处理libm时,没有任何未满足的符号,所以没有提取任何内容,导致无法工作。而对sqrt的未定义引用是在那之后产生的,而没有其他对象或库可以满足它。

我不知道是ld还是gcc链接器阶段有这种限制,我只是提出这种可能作为需要注意的事情。


谢谢!实际上,使用“-c”标志根本不会调用链接器,这是一个错误。但我尝试了没有-c标志的编译(gcc sparse_matrix.c -o sparse_matrix.o -Wall -pedantic -std=c99 -g -O -lm),但是我得到了一个未定义的引用“main”。正如我所说,我只是尝试做一个需要“libmath”中的“sqrt”函数的库“sparse_matrix”。 - Alexandre Pieroux
1
@Alex,请检查一下那个C文件中是否真的有main函数。考虑到你正在将编译和链接阶段分开,很可能它存在于另一个C文件中。如果你只是在创建一个带有对象的库(没有main函数),那么使用-c选项就可以了,但是当你的客户需要使用你的东西时,在链接时应该引入数学库:gcc client_stuff.c -lsparse_matrix_lib -lm ... - paxdiablo
是的,这就是我想做的。谢谢,我对库不是很熟悉,我以为我可以将一个库链接到另一个库中。对于这个相当简单的错误我感到抱歉。我刚刚尝试了一下我的主程序,它使用了这个库,现在(我明白了)它可以正常工作(只是在连接我自己的库的程序时添加了“-lm”,而不是在编译库的时候)。 :) 再次感谢您如此快速的回答! - Alexandre Pieroux

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