Почему не нужна ссылка libm?

#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 но можно использовать 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

4

Решение

В качестве оптимизации компилятор вычислил бы значение во время компиляции и использовал бы константу, поэтому нет вызова 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 файл).

6

Другие решения

Ты упомянул libstdc++ в комментарии, который заставляет меня подозревать, что проблема в том, что вы связываетесь с g++ а не с gcc,

gcc Команда вызывает компилятор и / или компоновщик. Если вы используете его для компиляции исходного файла, он обычно определяет язык (и, следовательно, какой интерфейс компилятора использовать).

g++ команда похожа, но она специализирована для C ++; если он вызывает компоновщик, он передает аргументы по мере необходимости, чтобы связать библиотеки, такие как libstdc++ которые требуются для C ++.

Например, эти две команды, которые просто компилируются без ссылок:

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 для других компиляторов это возможно ошибка.

1

По вопросам рекламы [email protected]