Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why it didn't need link libm?

Tags:

c++

c

gcc

libm

#include <math.h>
#include <stdio.h>
int main()
{
   printf("%f", roundf(3.14));
}

I compile above code (hasn't use -lm), add use ldd a.out, the result is

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)

why a.out didn't link with libm but can use roundf (or something like sqrt)? I have use nm to test libc.so.6 and ld-linux-x86064.so.2 but all of this didn't have the symbol of roundf.

I want to know where roundf defined, or it has be inlined by compiler? (test with gcc 4.7.3 and gcc 4.6.3)


The answer is http://fedoraproject.org/w/index.php?title=UnderstandingDSOLinkChange

like image 420
snyh Avatar asked Apr 25 '13 00:04

snyh


2 Answers

As an optimization, the compiler would have computed the value at compile time and used a constant, so there is no call to roundf() involved. You can verify this by seeing the generated code:

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

You can see that there is no call to roundf() in the generated assembly. (You can generate this with gcc -S filename.c and read the generated filename.s file).

like image 196
jman Avatar answered Sep 17 '22 23:09

jman


You mentioned libstdc++ in a comment, which makes me suspect that the problem is that you're linking with g++ rather than with gcc.

The gcc command invokes the compiler and/or the linker. If you use it to compile a source file, it normally determines the language (and therefore which compiler front-end to use).

The g++ command is similar, but it's specialized for C++; if it invokes the linker, it passes arguments as needed to link libraries like libstdc++ that are required for C++.

For example, these two commands, which just compile without linking:

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

are (as far as I know) equivalent, but these commands:

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

are not; the former will probably fail (depending on what features foo.cpp uses).

And it turns out that the g++ command, unlike the gcc command, implicitly links the math library, at least in the version on my system. So if your C++ code uses both C++-specific features (like, say, <iostream>) and math functions, then linking it with the gcc command is likely to produce complaints about functions defined in both libstdc++ and libm -- which is just what you're seeing.

If you link with the g++ command, that should solve the problem. You'll probably have to modify your Makefile or equivalent, or whatever generates it.

(If this is the solution, you should probably add "c++" to the list of tags on your question.)

As for why you didn't run into this problem before, I can't tell. Some C (and/or C++) compilers will link the math library implicitly; the need to specify -lm for other compilers is arguably a bug.

like image 20
Keith Thompson Avatar answered Sep 20 '22 23:09

Keith Thompson