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

标签 gcc ubuntu linker ld math.h

好吧,我觉得我的问题有点有趣,我想了解我的 Ubuntu 机器上发生了什么。

我用 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);
}

到目前为止一切顺利。但是当我改成这个时:

/* 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 但没有成功。

最佳答案

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

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

(如果你用

编译
gcc -S useless.c

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

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

gcc -o useless useless.c -lm

gcc useless.c -lm -o useless

链接器按顺序处理文件,跟踪每个文件的未解析符号(sin,由 useless.o 引用),然后按它看到的方式解析它们他们的定义。如果你把 -lm 放在前面,它在处理数学库时就没有未解析的符号;当它在 useless.o 中看到对 sin 的调用时,已经太晚了。

关于gcc - 与 'gcc' 和 '-lm' 相关的链接错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8957967/

相关文章:

c - 有没有办法获取 .exe 中包含的静态链接函数并重用它们?

objective-c - 在 PreferencePane 中使用框架

c++ - Binutils ld 链接器如何配置仿真模式(使用 mingw 构建后不支持仿真)

php - 使用 PHP 执行 FFMPEG shell - 由于 GCC 导致的异常错误

c - 尝试了解 GCC 和 Windows 的主要功能

gcc - 使用 arm-none-eabi-gcc 从 cpp 生成 elf 文件

gcc - C 编译器无法创建可执行文件 Ubuntu 10.04 LTS

ruby-on-rails - 在 heroku 安装 therubyracer,未能构建 gem native 扩展

Ubuntu中的rpy2安装错误

linux - 为什么 qemu 在尝试运行已经运行的操作系统的 VM 时会变黑?