与“gcc”相关的链接错误;和'-lm'

发布于 2024-12-28 07:26:06 字数 889 浏览 4 评论 0原文

嗯,我认为我的问题有点有趣,我想了解我的 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

茶花眉 2025-01-04 07:26:06

这里发生了两件不同的事情。

对于第一个示例,编译器不会生成对 sin 的调用。它看到参数是一个常量表达式,因此它用表达式的结果替换 sin(...) 调用,并且不需要数学库。没有 -lm 也能正常工作。 (但是您不应该指望这一点;编译器何时执行这种优化以及何时不执行这种优化并不总是显而易见的。)

(如果您使用 useless.s

gcc -S useless.c

并查看>,生成的汇编语言列表,您可以看到没有调用 sin。)

对于第二个示例,您确实需要 -lm 选项 - 但它需要位于命令行的末尾,或者至少在需要它的文件 (useless.c):

gcc -o useless useless.c -lm

或者

gcc useless.c -lm -o useless

链接器按顺序处理文件,跟踪每个文件的未解析符号 (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 the sin(...) 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

gcc -S useless.c

and take a look at useless.s, the generated assembly language listing, you can see that there's no call to sin.)

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:

gcc -o useless useless.c -lm

or

gcc useless.c -lm -o useless

The linker processes files in order, keeping track of unresolved symbols for each one (sin, referred to by useless.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 to sin in useless.o, it's too late.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文