为什么它不需要链接libm?
#include <math.h>
#include <stdio.h>
int main()
{
printf("%f", roundf(3.14));
}
我编译上面的代码(未使用-lm),添加使用LDD的a.out,结果是为什么它不需要链接libm?
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
作为一种优化,编译器会计算在编译时的值,并使用恒定,所以有是否涉及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 2013-04-25 00:42:36
@snyh:我建议你发布一个关于这个问题的新问题,使用一个不会让gcc优化调用的演示程序。我很惊讶你*不需要在gcc 4.6.3中使用'-lm'。但是加入'-lm'应该可以解决这个问题(假设它所抱怨的所有功能都是数学函数)。 – 2013-04-25 00:48:48
@KeithThompson对不起,但我不能构造一个简单的演示代码。 一个项目是webkitgtk-1.8.2,另一个是DDE(一个新的Linux桌面环境)。 DDE的代码和cmake文件是我写的,所以我可以确定我之前没有链接过libm,并且至少可以在三个月内编译OK。但是现在我必须明确地与libm链接.- 我想知道gcc中是否有一些技巧。或者是否有一些默认的链接库? - 它不仅在webkitgtk中报告libm而且报告了libstdC++。 – snyh 2013-04-25 00:57:38
您在评论中提到了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
使用的功能)。
事实证明,与gcc
命令不同,g++
命令隐含地链接了数学库,至少在我系统的版本中。所以,如果你的C++代码同时使用C++ - 特定功能(比如说,<iostream>
)和数学函数,然后用gcc
命令链接很容易产生约两个libstdc++
和libm
定义函数的抱怨 - 这正是你”重新看。
如果您使用g++
命令链接,那应该解决问题。你可能不得不修改Makefile
或同等学历,或任何其生成。
(如果是这样的解决方案,很可能需要添加“C++”来对你的问题的标记列表。)
至于你为什么没有遇到这个问题,我不知道。一些C(和/或C++)编译器将隐含地链接数学库;其他编译器需要指定-lm
可以说是一个错误。
我发现关键是“ld的默认行为允许用户通过中间对象/库'间接'链接到所需的对象/库”。 ([链接] http://fedoraproject.org/w/index.php?title=UnderstandingDSOLinkChange),但现在它不能:( – snyh 2013-04-25 03:04:29
这些存在于libc IIRC中。 – 2013-04-25 00:26:40
IIRC代表交叉工具吗? – snyh 2013-04-25 00:32:45
IIRC =“如果我记得正确” – Tim 2013-04-25 00:41:57