【问题标题】:Why it didn't need link libm?为什么它不需要链接 libm?
【发布时间】:2013-04-25 00:25:19
【问题描述】:
#include <math.h>
#include <stdio.h>
int main()
{
   printf("%f", roundf(3.14));
}

我编译上面的代码(没用-lm),加上use ldd a.out,结果是

linux-vdso.so.1 =>  (0x00007fffab9ff000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd6da0f8000)
/lib64/ld-linux-x86-64.so.2 (0x00007fd6da4eb000)

为什么 a.out 没有与 libm 链接但可以使用 roundf(或类似 sqrt 的东西)? 我使用 nm 来测试 libc.so.6 和 ld-linux-x86064.so.2 但所有这些都没有 roundf 的符号。

我想知道 roundf 是在哪里定义的,还是被编译器内联了? (使用 gcc 4.7.3 和 gcc 4.6.3 进行测试)


答案是http://fedoraproject.org/w/index.php?title=UnderstandingDSOLinkChange

【问题讨论】:

  • 这些存在于 libc IIRC 中。
  • IIRC 代表跨工具吗??
  • IIRC = "如果我没记错的话"
  • 谢谢你的解释@Tim

标签: c++ c gcc libm


【解决方案1】:

作为一种优化,编译器会在编译时计算该值并使用一个常量,因此不涉及对roundf() 的调用。您可以通过查看生成的代码来验证这一点:

main:
    pushl   %ebp
    movl    %esp, %ebp
    andl    $-16, %esp
    subl    $16, %esp
    movl    $.LC0, %eax
    fldl    .LC1
    fstpl   4(%esp)
    movl    %eax, (%esp)
    call    printf
    leave
    ret

您可以看到在生成的程序集中没有对roundf() 的调用。 (您可以使用gcc -S filename.c 生成此文件并读取生成的filename.s 文件)。

【讨论】:

  • 哦,我太傻了。-但最初的问题是我有一些项目可以用 gcc 4.6.3 编译,但是当我更新我的系统时(Deepin,一个基于 Ubuntu 的中文发行版)许多项目无法成功编译。 gcc 报告找不到 roundf 并告诉我手动链接这些库。 (有很多未定义的函数)我不明白为什么。
  • @snyh:我建议你发布一个关于这个问题的新问题,使用一个不允许 gcc 优化调用的演示程序。我很惊讶您不需要-lm 与 gcc 4.6.3 一起使用。但是添加 -lm 应该可以解决问题(假设它抱怨的所有函数都是数学函数)。
  • @KeithThompson 抱歉,我无法构造简单的演示代码。一个项目是 webkitgtk-1.8.2,另一个是 DDE(一个新的 linux 桌面环境)。 DDE的代码和cmake文件是我写的,所以我可以确定我之前没有链接libm,它至少可以编译三个月。但是现在我必须明确地与 libm 链接。-我想知道 gcc 中是否有一些技巧。还是有一些默认的链接库?-它不仅报告了libm,还报告了webkitgtk中的libstdc++。
  • 在尝试编译之前,您/您的构建系统是否在每个包上运行./configure?还是它使用以前创建的配置?
【解决方案2】:

您在评论中提到了libstdc++,这让我怀疑问题在于您链接的是g++,而不是gcc

gcc 命令调用编译器和/或链接器。如果您使用它来编译源文件,它通常会确定语言(以及使用哪个编译器前端)。

g++ 命令类似,但它专门用于 C++;如果它调用链接器,它会根据需要传递参数以链接 C++ 所需的 libstdc++ 等库。

比如这两个命令,直接编译不链接:

gcc -c foo.cpp
g++ -c foo.cpp

(据我所知)是等效的,但是这些命令:

gcc foo.cpp -o foo
g++ foo.cpp -o foo

不是;前者可能会失败(取决于 foo.cpp 使用的功能)。

事实证明,g++ 命令与gcc 命令不同,它隐式链接了数学库,至少在我系统上的版本中是这样。因此,如果您的 C++ 代码同时使用 C++ 特定功能(例如,&lt;iostream&gt;)和数学函数,那么将其与 gcc 命令链接可能会产生对 libstdc++libm 中定义的函数的抱怨-- 这正是你所看到的。

如果您使用g++ 命令链接,那应该可以解决问题。您可能需要修改您的 Makefile 或等效项,或者生成它的任何内容。

(如果这是解决方案,您可能应该在问题的标签列表中添加“c++”。)

至于你之前为什么没有遇到这个问题,我说不上来。一些 C(和/或 C++)编译器会隐式链接数学库;需要为其他编译器指定 -lm 可以说是一个错误。

【讨论】:

猜你喜欢
  • 2011-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-06
  • 2019-01-16
  • 1970-01-01
相关资源
最近更新 更多