#include <math.h>
#include <stdio.h>
int main()
{
printf("%f", roundf(3.14));
}我编译了上面的代码(没有使用-lm),添加使用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,但是可以使用圆形(或者类似sqrt之类的东西)?我使用nm测试libc.so.6和didn x86064.so.2,但所有这些都没有圆f的符号。
我想知道圆f是在哪里定义的,还是已经被编译器内联了?(与gcc 4.7.3和gcc 4.6.3进行测试)
答案是http://fedoraproject.org/w/index.php?title=UnderstandingDSOLinkChange
发布于 2013-04-25 00:29:28
作为优化,编译器将在编译时计算值并使用常量,因此不需要调用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文件)。
发布于 2013-04-25 01:16:16
您在一条评论中提到了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++的特性(例如,<iostream>)和数学函数,那么将其与gcc命令链接可能会产生对libstdc++和libm中定义的函数的抱怨--这正是您所看到的。
如果您链接到g++命令,这将解决问题。您可能需要修改您的Makefile或等效的,或者任何生成它的东西。
(如果这是解决方案,您可能应该在问题的标签列表中添加"c++“。)
至于你以前为什么没有遇到这个问题,我不知道。一些C(和/或C++)编译器将隐式地链接数学库;为其他编译器指定-lm的需要可以说是一个错误。
https://stackoverflow.com/questions/16204457
复制相似问题