2013-04-25 6 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.

Я хочу знать, где определен круглый круг, или он был встроен компилятором? (тест с GCC 4.7.3 и GCC 4.6.3)


Ответ является http://fedoraproject.org/w/index.php?title=UnderstandingDSOLinkChange

+0

Они представлены в libc IIRC. –

+0

Подставка IIRC для перекрестных инструментов? – snyh

+1

IIRC = «если я правильно помню» – Tim

ответ

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

+0

@snyh: Предлагаю вам опубликовать новый вопрос об этой проблеме, используя демонстрационную программу, которая не позволяет gcc оптимизировать вызов. Я удивлен, что вам не понадобилось использовать '-lm' с gcc 4.6.3. Но добавление '-lm' должно устранить проблему (предполагая, что все функции, о которых он жалуется, являются математическими функциями). –

+0

@KeithThompson Извините, но я не могу создать простой демонстрационный код. Один проект - webkitgtk-1.8.2, а другой - DDE (новая среда рабочего стола linux). Код DDE и файл cmake - это моя запись, поэтому я уверен, что раньше я не связывал libm, и он может скомпилировать OK как минимум три месяца. Но теперь я должен связаться с libm явно. - Я хочу знать, есть ли какой-то трюк в gcc. Или есть некоторые библиотеки ссылок по умолчанию? - Он не только сообщал libm, но также и libstdC++ в webkitgtk. – snyh

1

Вы упомянули 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 для других компиляторов, возможно, является ошибкой.

+0

Я нашел ключ: «Поведение по умолчанию для ld позволяет пользователям« косвенно »ссылаться на требуемые объекты/библиотеки через промежуточные объекты/библиотеки». ([link] http://fedoraproject.org/w/index.php?title=UnderstandingDSOLinkChange), но теперь он не может :( – snyh

Смежные вопросы