2013-04-25 100 views
4
#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

+0

这些存在于libc IIRC中。 – 2013-04-25 00:26:40

+0

IIRC代表交叉工具吗? – snyh 2013-04-25 00:32:45

+1

IIRC =“如果我记得正确” – Tim 2013-04-25 00:41:57

回答

6

作为一种优化,编译器会计算在编译时的值,并使用恒定,所以有是否涉及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文件)。

+0

哦,我太愚蠢了.- 但是最初的问题是我有一些项目被编译好用gcc 4.6.3但是当我更新我的系统Deepin,基于Ubuntu的中文发行版)很多项目都无法成功编译。 gcc报告无法找到roundf并告诉我手动链接这些库。 (有很多未定义的功能) 我不明白为什么。 – snyh 2013-04-25 00:42:36

+0

@snyh:我建议你发布一个关于这个问题的新问题,使用一个不会让gcc优化调用的演示程序。我很惊讶你*不需要在gcc 4.6.3中使用'-lm'。但是加入'-lm'应该可以解决这个问题(假设它所抱怨的所有功能都是数学函数)。 – 2013-04-25 00:48:48

+0

@KeithThompson对不起,但我不能构造一个简单的演示代码。 一个项目是webkitgtk-1.8.2,另一个是DDE(一个新的Linux桌面环境)。 DDE的代码和cmake文件是我写的,所以我可以确定我之前没有链接过libm,并且至少可以在三个月内编译OK。但是现在我必须明确地与libm链接.- 我想知道gcc中是否有一些技巧。或者是否有一些默认的链接库? - 它不仅在webkitgtk中报告libm而且报告了libstdC++。 – snyh 2013-04-25 00:57:38

1

您在评论中提到了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可以说是一个错误。

+0

我发现关键是“ld的默认行为允许用户通过中间对象/库'间接'链接到所需的对象/库”。 ([链接] http://fedoraproject.org/w/index.php?title=UnderstandingDSOLinkChange),但现在它不能:( – snyh 2013-04-25 03:04:29