2012-01-25 2 views
8

Я пытался создать код, который использует математические функции (например, pow).Странное поведение gcc и math.h?

math.h прилагается, а флаг -lm используется во время сборки.

Когда компиляция называется, как это (-lm флаг в начале команды), он не смог, сказав, что есть неопределенная ссылка на pow:

gcc -lm -O3 main.o clustering.o grassberger.o hash.o list.o mat.o metropolis.o motif_ids.o output.o permutation.o prob.o random.o results.o role.o stubs.o switches.o -o mfinder 
main.o: In function `get_sn_motif_id': 
main.c:(.text+0x28d): undefined reference to `pow' 

И когда -lm флаг ставится на конец команды, это работает!

gcc -O3 main.o clustering.o grassberger.o hash.o list.o mat.o metropolis.o motif_ids.o output.o permutation.o prob.o random.o results.o role.o stubs.o switches.o -o mfinder -lm 

Это нормально?

+0

Упс. Не заметил, что это старый вопрос. – AnT

ответ

18

Да, это нормально. Для многих компоновщиков важно указать порядок, в котором вы указываете объектные файлы и библиотеки.

Цитирую "An Introduction to GCC - for the GNU compilers gcc and g++":

Традиционное поведение линкера является поиск внешних функций слева направо в библиотеках, указанных в командной строке. Это означает, что библиотека, содержащая определение функции, должна появляться после любых исходных файлов или файлов объектов, которые ее используют. Это включает в себя библиотеку, указанную с короткой резкой -l опции, как показано в следующей команде:

$ gcc -Wall calc.c -lm -o calc (correct order)

Такого поведение является обычным явлением, но отнюдь не универсально. Если у вас есть сомнения, лучше проконсультироваться с руководством вашего линкера. Например, в моей системе Ubuntu man ld утверждает, что:

-l namespec 
    --library=namespec 

     ... 

     The linker will search an archive only once, at the location where 
     it is specified on the command line. If the archive defines a 
     symbol which was undefined in some object which appeared before the 
     archive on the command line, the linker will include the 
     appropriate file(s) from the archive. However, an undefined symbol 
     in an object appearing later on the command line will not cause the 
     linker to search the archive again. 

Другими словами, этот линкер действительно ведет себя так, как описано в книге gcc.

+0

Хотя следует упомянуть, что это не применялось к общим библиотекам (по крайней мере, с gcc), они могли появляться в любой точке командной строки. Так люди это сделали.Однако недавно это изменилось, gcc теперь применяет флаг '--as-needed' к компоновщику на многих платформах, поэтому эффект одинаковый для разделяемых библиотек. – nos

4

Как уже упоминалось в An Introduction to GCC - for the GNU compilers gcc and g++

Традиционное поведение линкера является поиск внешних функций слева направо в библиотеках, указанных в командной строке. Это означает, что библиотека, содержащая определение функции, должна появляться после любых исходных файлов или файлов объектов, которые ее используют.

Я думаю, что вы видите то же поведение.

Обратите внимание, что это также далее говорится,

Большинство современных линкеров поиск всех библиотек, независимо от того, но лучше следовать соглашению о заказе библиотек слева направо.