c++ - स्नातक होने के बाद लाइब्रेरियन पाठ्यक्रम




ऑर्डर किस पुस्तकालय से जुड़ा हुआ है कभी-कभी जीसीसी में त्रुटियों का कारण बनता है? (7)

आप -Xlinker विकल्प का उपयोग कर सकते हैं।

g++ -o foobar  -Xlinker -start-group  -Xlinker libA.a -Xlinker libB.a -Xlinker libC.a  -Xlinker -end-group 

के बराबर बराबर है

g++ -o foobar  -Xlinker -start-group  -Xlinker libC.a -Xlinker libB.a -Xlinker libA.a  -Xlinker -end-group 

सावधान!

  1. एक समूह के भीतर आदेश महत्वपूर्ण है! यहां एक उदाहरण दिया गया है: एक डीबग लाइब्रेरी में डीबग दिनचर्या है, लेकिन गैर-डीबग लाइब्रेरी का एक कमजोर संस्करण है। आपको समूह में पहली बार डीबग लाइब्रेरी डालना होगा या आप गैर-डीबग संस्करण को हल करेंगे।
  2. आपको समूह सूची में -Xlinker के साथ प्रत्येक लाइब्रेरी से पहले की आवश्यकता है

ऑर्डर किस पुस्तकालय से जुड़ा हुआ है कभी-कभी जीसीसी में त्रुटियों का कारण बनता है?


एक और विकल्प पुस्तकालयों की सूची दो बार निर्दिष्ट करना होगा:

gcc prog.o libA.a libB.a libA.a libB.a -o prog.x

ऐसा करने से, आपको सही अनुक्रम से परेशान करने की आवश्यकता नहीं है क्योंकि संदर्भ दूसरे ब्लॉक में हल किया जाएगा।


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

ठेठ यूनिक्स लिंकर बाएं से दाएं काम करता है, इसलिए बाईं ओर अपने सभी निर्भर पुस्तकालयों को रखें, और वे लिंक लाइन के दाईं ओर उन निर्भरताओं को पूरा करते हैं। आप पाते हैं कि कुछ पुस्तकालय दूसरों पर निर्भर करते हैं जबकि साथ ही अन्य पुस्तकालय उन पर निर्भर करते हैं। यह वह जगह है जहां यह जटिल हो जाता है। जब परिपत्र संदर्भों की बात आती है, तो अपना कोड ठीक करें!


मुझे लगता है कि ऐसा इसलिए है क्योंकि उन पुस्तकालयों में से कुछ अन्य पुस्तकालयों पर निर्भरता रखते हैं, और यदि वे अभी तक लिंक नहीं किए गए हैं तो आपको लिंकर त्रुटियां मिलेंगी।


यदि आप -Wl,--start-group जोड़ते हैं -Wl,--start-group लिंकर झंडे के लिए -Wl,--start-group , यह परवाह नहीं करता कि वे किस क्रम में हैं या यदि परिपत्र निर्भरताएं हैं।

क्यूटी पर इसका मतलब है:

QMAKE_LFLAGS += -Wl,--start-group

समय के साथ गड़बड़ी के भार को बचाता है और यह बहुत अधिक लिंक करने में धीमा प्रतीत नहीं होता है (जो संकलन से कहीं कम समय लेता है)।


लिंक ऑर्डर निश्चित रूप से कम से कम कुछ प्लेटफॉर्म पर मायने रखता है। मैंने गलत क्रम में पुस्तकालयों से जुड़े अनुप्रयोगों के लिए दुर्घटनाएं देखी हैं (जहां गलत मतलब है बी बी से पहले जुड़ा हुआ है लेकिन बी ए पर निर्भर करता है)।


(अधिक विस्तृत पाठ प्राप्त करने के लिए इस उत्तर पर इतिहास देखें, लेकिन अब मुझे लगता है कि पाठक के लिए वास्तविक कमांड लाइन देखना आसान है)।

सभी नीचे दिए गए आदेशों द्वारा साझा की जाने वाली सामान्य फ़ाइलें

$ cat a.cpp
extern int a;
int main() {
  return a;
}

$ cat b.cpp
extern int b;
int a = b;

$ cat d.cpp
int b;

स्थिर पुस्तकालयों से जुड़ा हुआ है

$ g++ -c b.cpp -o b.o
$ ar cr libb.a b.o
$ g++ -c d.cpp -o d.o
$ ar cr libd.a d.o

$ g++ -L. -ld -lb a.cpp # wrong order
$ g++ -L. -lb -ld a.cpp # wrong order
$ g++ a.cpp -L. -ld -lb # wrong order
$ g++ a.cpp -L. -lb -ld # right order

लिंकर बाएं से दाएं की खोज करता है, और यह अनसुलझे प्रतीकों को नोट करता है। यदि कोई लाइब्रेरी प्रतीक को हल करती है, तो प्रतीक को हल करने के लिए उस लाइब्रेरी की ऑब्जेक्ट फ़ाइलें लेती हैं (इस मामले में libb.a से बाहर)।

एक दूसरे के खिलाफ स्थैतिक पुस्तकालयों की निर्भरता समान कार्य करती है - लाइब्रेरी जिन्हें प्रतीकों की आवश्यकता होती है, वह पहले होना चाहिए, फिर पुस्तकालय जो प्रतीक को हल करता है।

यदि एक स्थिर पुस्तकालय किसी अन्य पुस्तकालय पर निर्भर करता है, लेकिन दूसरी लाइब्रेरी फिर से पूर्व पुस्तकालय पर निर्भर करती है, तो एक चक्र होता है। आप चक्रीय रूप से निर्भर पुस्तकालयों को -( और -) , जैसे -( -la -lb -) द्वारा संलग्न करके हल कर सकते हैं (आपको -( -la -lb -) से बचने की आवश्यकता हो सकती है, जैसे -\( और -\) )। तब लिंकर साइक्लिंग निर्भरताओं को हल करने के लिए उन संलग्न lib कई बार खोजता है। वैकल्पिक रूप से, आप पुस्तकालयों को कई बार निर्दिष्ट कर सकते हैं, इसलिए प्रत्येक एक दूसरे से पहले है: -la -lb -la

गतिशील पुस्तकालयों से जुड़ा हुआ है

$ export LD_LIBRARY_PATH=. # not needed if libs go to /usr/lib etc
$ g++ -fpic -shared d.cpp -o libd.so
$ g++ -fpic -shared b.cpp -L. -ld -o libb.so # specifies its dependency!

$ g++ -L. -lb a.cpp # wrong order (works on some distributions)
$ g++ -Wl,--as-needed -L. -lb a.cpp # wrong order
$ g++ -Wl,--as-needed a.cpp -L. -lb # right order

यह वही है - पुस्तकालयों को कार्यक्रम की ऑब्जेक्ट फाइलों का पालन करना होगा। स्थिर पुस्तकालयों के साथ यहां अंतर यह है कि आपको एक दूसरे के खिलाफ पुस्तकालयों की निर्भरताओं पर ध्यान नहीं देना चाहिए, क्योंकि गतिशील पुस्तकालय अपनी निर्भरताओं को स्वयं हल करते हैं

कुछ हालिया वितरण स्पष्ट रूप से --as-needed लिंकर ध्वज का उपयोग करने के लिए डिफ़ॉल्ट हैं, जो लागू करता है कि प्रोग्राम की ऑब्जेक्ट फ़ाइलें गतिशील पुस्तकालयों से पहले आती हैं। यदि वह ध्वज पास हो गया है, तो लिंकर उन लाइब्रेरी से लिंक नहीं करेगा जिन्हें वास्तव में निष्पादन योग्य द्वारा आवश्यक नहीं है (और यह बाएं से दाएं से इसका पता लगाता है)। मेरा हालिया archlinux वितरण डिफ़ॉल्ट रूप से इस ध्वज का उपयोग नहीं करता है, इसलिए यह सही क्रम का पालन न करने में त्रुटि नहीं देता है।

पूर्व बनाते समय b.so खिलाफ d.so की निर्भरता को छोड़ना सही नहीं है। तब आपको लाइब्रेरी निर्दिष्ट करने की आवश्यकता होगी, लेकिन a को वास्तव में पूर्णांक b आवश्यकता नहीं है, इसलिए इसे b की अपनी निर्भरताओं की देखभाल करने के लिए नहीं बनाया जाना चाहिए।

यदि आप libb.so लिए निर्भरताओं को निर्दिष्ट करना याद करते हैं तो यहां प्रभावों का एक उदाहरण libb.so

$ export LD_LIBRARY_PATH=. # not needed if libs go to /usr/lib etc
$ g++ -fpic -shared d.cpp -o libd.so
$ g++ -fpic -shared b.cpp -o libb.so # wrong (but links)

$ g++ -L. -lb a.cpp # wrong, as above
$ g++ -Wl,--as-needed -L. -lb a.cpp # wrong, as above
$ g++ a.cpp -L. -lb # wrong, missing libd.so
$ g++ a.cpp -L. -ld -lb # wrong order (works on some distributions)
$ g++ -Wl,--as-needed a.cpp -L. -ld -lb # wrong order (like static libs)
$ g++ -Wl,--as-needed a.cpp -L. -lb -ld # "right"

यदि अब आप बाइनरी की निर्भरताओं को देखते हैं, तो आप ध्यान दें कि द्विआधारी भी libd पर निर्भर करता है, न केवल libb रूप में। अगर libb बाद में libb को दूसरी लाइब्रेरी पर निर्भर करते हैं, तो बाइनरी को फिर से libb , अगर आप इसे इस तरह करते हैं। और अगर कोई और रनटाइम पर dlopen का उपयोग करके libb लोड करता है (गतिशील रूप से प्लगइन लोड करने के बारे में सोचें), तो कॉल भी असफल हो जाएगी। तो "right" वास्तव में भी wrong होना चाहिए।





linker