2012-07-04 17 views
16

यहाँ एक न्यूनतम उदाहरण मेरी समस्या रूपरेखा हैजीसीसी ठीक से नहीं शामिल होंगे math.h

test.c:

#include <stdio.h> 
#include <math.h> 

main() 
{ 
    fmod (3, 2); 
} 

और यहाँ है आदेश मैं जारी करने हूँ test.c

संकलित करने के लिए
gcc -lm test.c -o test 

और जब मैं उपरोक्त आदेश

जारी करता हूं तो आउटपुट मुझे मिलता है
/tmp/ccQmRk99.o: In function `main': 
test.c:(.text+0x3e): undefined reference to `fmod' 
collect2: ld returned 1 exit status 

यदि मैं cc का उपयोग करता हूं तो मुझे वही आउटपुट मिलता है। मैं gcc

gcc-4.6.real (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1 

कोई भी विचार क्यों मेरा प्रोग्राम संकलित नहीं करेगा?

+0

इस कोड को संकलित करता है तथा जीसीसी 4.1.2 और 4.3.4 के साथ मेरे लिए ठीक लिंक ... –

+0

@OliCharlesworth मैं सचमुच यह के सभी स्पष्ट रूप से चिपकाया कॉपी करके मेरे लिए काम नहीं करता – puk

+0

@OliCharlesworth क्या यह संभव है math.h शामिल नहीं किया जा रहा है? – puk

उत्तर

46

समस्या जीसीसी (इसलिए बाहर निकलने की स्थिति संदेश) के बजाय लिंकर, ld से आ रही है। सामान्य एलडी में वस्तुओं और पुस्तकालयों को क्रमशः usersupplier में निर्दिष्ट करने की आवश्यकता होती है, जहां user एक ऑब्जेक्ट है जो लाइब्रेरी फ़ंक्शन का उपयोग करता है और supplier वह ऑब्जेक्ट है जो इसे प्रदान करता है।

जब आपके test.c किसी ऑब्जेक्ट को संकलित किया गया है संकलक कहा गया है कि fmod एक अपरिभाषित संदर्भ है

$ gcc -c test.c 
$ nm test.o 
       U fmod 
0000000000000000 T main 

(एनएम एक वस्तु फ़ाइल से सभी कार्यों के लिए भेजा सूचीबद्ध करता है)

लिंकर अपरिभाषित में परिवर्तन परिभाषित लोगों के संदर्भ, संदर्भ देखने के लिए कि क्या वे अन्य फाइलों में आपूर्ति की जाती हैं।

$ gcc -lm test.o 
$ nm a.out 
0000000000600e30 d _DYNAMIC 
0000000000600fe8 d _GLOBAL_OFFSET_TABLE_ 
00000000004006a8 R _IO_stdin_used 
       w _Jv_RegisterClasses 
0000000000600e10 d __CTOR_END__ 
... 
0000000000601018 D __dso_handle 
       w __gmon_start__ 
... 
       U [email protected]@GLIBC_2.2.5 
0000000000601020 A _edata 
0000000000601030 A _end 
0000000000400698 T _fini 
0000000000400448 T _init 
0000000000400490 T _start 
00000000004004bc t call_gmon_start 
0000000000601020 b completed.7382 
0000000000601010 W data_start 
0000000000601028 b dtor_idx.7384 
       U [email protected]@GLIBC_2.2.5 
0000000000400550 t frame_dummy 
0000000000400574 T main 

इनमें से अधिकांश libc फ़ंक्शंस का संदर्भ लेते हैं जो पर्यावरण को स्थापित करने के लिए पहले और बाद में चलाए जाते हैं। आप देख सकते हैं कि fmod अब glibc को इंगित करता है, जहां इसे साझा लाइब्रेरी सिस्टम द्वारा हल किया जाएगा।

मेरा सिस्टम डिफ़ॉल्ट रूप से साझा पुस्तकालयों का उपयोग करने के लिए सेट अप किया गया है। मैं बजाय आंकड़े जोड़ने के लिए मजबूर अगर मैं आदेश प्राप्त निर्भरता आप देख

$ gcc -static -lm test.o 
test.o: In function `main': 
test.c:(.text+0x40): undefined reference to `fmod' 
collect2: ld returned 1 exit status 

बाद में लाना -lm लिंकर आदेश में, के बाद test.o, इसे सफलतापूर्वक लिंक करने के लिए अनुमति देता है। प्रतीकों fmod जाँच हो रही है अब एक वास्तविक पते में समाधान किया जाना चाहिए, और वास्तव में यह

$ gcc -static test.o -lm 
$ nm a.out | grep fmod 
0000000000400480 T __fmod 
0000000000402b80 T __ieee754_fmod 
0000000000400480 W fmod 
+0

लिंकेज प्रक्रिया का एक बहुत अच्छा स्पष्टीकरण, लेकिन नीचे की रेखा अस्पष्ट है। क्या आप कह रहे हैं कि '-lm test.o' से' test.o -lm' में परिवर्तन समस्या हल करता है (और इसलिए, उसे 'gcc -lm test.c -o test' को' gcc test.c में बदलना चाहिए - एलएम -ओ टेस्ट')? – ugoren

+7

हां। जब तक आपके पास अन्यथा आवश्यकतानुसार कोई विशिष्ट कारण न हो, पुस्तकालय ** हमेशा आपकी लिंक कमांड लाइन के अंत ** से संबंधित होते हैं। और वे निर्भरता आदेश में हैं, यानी यदि ए बी पर निर्भर करता है, बी हमेशा कमांड लाइन पर ए के बाद आना चाहिए। –

+0

अच्छा जवाब, मैं कभी भी "एनएम" के बारे में नहीं जानता था। –

2
जीसीसी (1) मैनपेज से

है: "। -l विकल्प के स्थान महत्वपूर्ण है"

विशेष रूप से:

-llibrary 
    -l library 
     Search the library named library when linking. (The second alternative with the library as a 
     separate argument is only for POSIX compliance and is not recommended.) 

     It makes a difference where in the command you write this option; the linker searches and processes 
     libraries and object files in the order they are specified. Thus, foo.o -lz bar.o searches library z 
     after file foo.o but before bar.o. If bar.o refers to functions in z, those functions may not be 
     loaded. 

     The linker searches a standard list of directories for the library, which is actually a file named 
     liblibrary.a. The linker then uses this file as if it had been specified precisely by name. 

     The directories searched include several standard system directories plus any that you specify with 
     -L. 

     Normally the files found this way are library files---archive files whose members are object files. 
     The linker handles an archive file by scanning through it for members which define symbols that have 
     so far been referenced but not defined. But if the file that is found is an ordinary object file, it 
     is linked in the usual fashion. The only difference between using an -l option and specifying a file 
     name is that -l surrounds library with lib and .a and searches several directories. 
संबंधित मुद्दे