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