与“gcc”相关的链接错误;和'-lm'
嗯,我认为我的问题有点有趣,我想了解我的 Ubuntu 机器上发生了什么。
我使用 gcc -lm -o 无用的unused.c
编译并链接了以下无用的代码:
/* File useless.c */
#include <stdio.h>
#include <math.h>
int main()
{
int sample = (int)(0.75 * 32768.0 * sin(2 * 3.14 * 440 * ((float) 1/44100)));
return(0);
}
到目前为止一切顺利。但是当我更改为:
/* File useless.c */
#include <stdio.h>
#include <math.h>
int main()
{
int freq = 440;
int sample = (int)(0.75 * 32768.0 * sin(2 * 3.14 * freq * ((float) 1/44100)));
return(0);
}
并且我尝试使用相同的命令行进行编译时,gcc
响应:
/tmp/cctM0k56.o: In function `main':
ao_example3.c:(.text+0x29): undefined reference to `sin'
collect2: ld returned 1 exit status
并且它停止了。怎么了?为什么我不能这样编译?
我还尝试了 sudo ldconfig -v
但没有成功。
Well, I think my problem is a little bit interesting and I want to understand what's happening on my Ubuntu box.
I compiled and linked the following useless piece of code with gcc -lm -o useless useless.c
:
/* File useless.c */
#include <stdio.h>
#include <math.h>
int main()
{
int sample = (int)(0.75 * 32768.0 * sin(2 * 3.14 * 440 * ((float) 1/44100)));
return(0);
}
So far so good. But when I change to this:
/* File useless.c */
#include <stdio.h>
#include <math.h>
int main()
{
int freq = 440;
int sample = (int)(0.75 * 32768.0 * sin(2 * 3.14 * freq * ((float) 1/44100)));
return(0);
}
And I try to compile using the same command line, and gcc
responds:
/tmp/cctM0k56.o: In function `main':
ao_example3.c:(.text+0x29): undefined reference to `sin'
collect2: ld returned 1 exit status
And it stops. What is happening? Why can't I compile that way?
I also tried a sudo ldconfig -v
without success.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这里发生了两件不同的事情。
对于第一个示例,编译器不会生成对
sin
的调用。它看到参数是一个常量表达式,因此它用表达式的结果替换sin(...)
调用,并且不需要数学库。没有-lm
也能正常工作。 (但是您不应该指望这一点;编译器何时执行这种优化以及何时不执行这种优化并不总是显而易见的。)(如果您使用
useless.s
并查看>,生成的汇编语言列表,您可以看到没有调用
sin
。)对于第二个示例,您确实需要
-lm
选项 - 但它需要位于命令行的末尾,或者至少在需要它的文件 (useless.c
):或者
链接器按顺序处理文件,跟踪每个文件的未解析符号 (
sin
,由useless 引用) .o
),然后在看到它们的定义时解析它们。如果将-lm
放在前面,则在处理数学库时不会有未解析的符号;当它在useless.o
中看到对sin
的调用时,已经太晚了。There are two different things going on here.
For the first example, the compiler doesn't generate a call to
sin
. It sees that the argument is a constant expression, so it replaces thesin(...)
call with the result of the expression, and the math library isn't needed. It will work just as well without the-lm
. (But you shouldn't count on that; it's not always obvious when the compiler will perform this kind of optimization and when it won't.)(If you compile with
and take a look at
useless.s
, the generated assembly language listing, you can see that there's no call tosin
.)For the second example, you do need the
-lm
option -- but it needs to be at the end of the command line, or at least after the file (useless.c
) that needs it:or
The linker processes files in order, keeping track of unresolved symbols for each one (
sin
, referred to byuseless.o
), and then resolving them as it sees their definitions. If you put the-lm
first, there are no unresolved symbols when it processes the math library; by the time it sees the call tosin
inuseless.o
, it's too late.