c++ - क्या अप्रयुक्त लिब्जेस के संबंध से बचने के लिए सी++ लिंक काफी चालाक है?




linker (3)

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

एक स्थैतिक पुस्तकालय मुख्यतः ऐसे नोड्स (+ एक सूचकांक) की सूची है।

कार्यक्रम शुरू नोड main() फ़ंक्शन है।
लिंकर main() से ग्राफ को पार करता है और निष्पादन योग्य सभी नोड्स में लिंक करता है जो main() से पहुंच योग्य हैं। यही कारण है कि इसे एक लिंकर कहा जाता है (कार्यान्वयन के भीतर फ़ंक्शन कॉल पतों को जोड़ना मानचित्र)

अप्रयुक्त फ़ंक्शन, main() से उत्पन्न ग्राफ में नोड से लिंक नहीं है
इस प्रकार, ऐसे डिस्कनेक्ट किए गए नोड्स तक पहुंचने योग्य नहीं हैं और अंतिम निष्पादन योग्य में शामिल नहीं हैं।

निष्पादन योग्य (स्थिर लाइब्रेरी के विपरीत) मुख्य रूप से main() (+ एक अन्य सूचकांक और अन्य चीजों के बीच स्टार्टअप कोड main() से पहुंचने वाले सभी नोड्स की एक सूची है।

मैं पूरी तरह से समझ रहा हूं कि सी ++ लिंकर कैसे काम करता है और मेरे पास इसके बारे में एक विशिष्ट प्रश्न है।

कहो मेरे पास निम्न है:

Utils.h

namespace Utils
{
    void func1();
    void func2();
}

Utils.cpp

#include "some_huge_lib" // needed only by func2()

namespace Utils
{
    void func1() { /* do something */ }
    void func2() { /* make use of some functions defined in some_huge_lib */ }
}

main.cpp

int main()
{
  Utils::func1()
}

मेरा लक्ष्य संभव के रूप में छोटे बाइनरी फ़ाइलों के रूप में उत्पन्न करना है

मेरा सवाल है, क्या some_huge_lib को आउटपुट ऑब्जेक्ट फ़ाइल में शामिल किया जाएगा?


यह लिंक और संकलन करने के लिए उपकरण और स्विचेस के उपयोग पर बहुत निर्भर करता है।

सबसे पहले, यदि साझा किए गए लाइब्रेरी के रूप में some_huge_lib को लिंक some_huge_lib जाता है, तो साझा लाइब्रेरी को जोड़ने पर सभी कोड और निर्भरता को हल करने की आवश्यकता होगी। तो हाँ, यह कहीं में खींच लिया जाएगा

यदि आप some_huge_lib को एक संग्रह के रूप में लिंक some_huge_lib , तो - यह निर्भर करता है। पाठक को अलग-अलग स्रोत कोड फ़ाइलों में मजेदार और मजेदार सीडी रखने के लिए पाठक की विवेक के लिए यह अच्छा अभ्यास है, इस मामले में सामान्यतः लिंकर अप्रयुक्त ऑब्जेक्ट फाइलों और उनकी निर्भरता को अनदेखा कर पाएगा।

यदि आपके पास एक ही फ़ाइल में दोनों फ़ंक्शन हैं, तो आप, कुछ कम्पाइलर पर, उन्हें प्रत्येक फ़ंक्शन के लिए अलग-अलग अनुभागों का उत्पादन करने के लिए कहने की आवश्यकता होगी। कुछ कंपलर स्वत: यह करते हैं, कुछ इसे बिल्कुल भी नहीं करते हैं। यदि आपके पास यह विकल्प नहीं है, तो func1 में खींचकर func2 के लिए सभी कोड खींचें, और सभी निर्भरता को हल करने की आवश्यकता होगी।


बड़े पुस्तकालयों के साथ शामिल करना या लिंक करना आम तौर पर कोई फर्क नहीं पड़ेगा जब तक आप उस सामान का उपयोग नहीं करते। लिंकर्स को मृत कोड निष्कासन करना चाहिए और इस प्रकार यह सुनिश्चित करना चाहिए कि बिल्ड समय पर आप बहुत अधिक अप्रयुक्त कोड वाले बड़े बाइनरी नहीं पाएंगे (अपने कंपाइलर / लिंकर मैनुअल को और जानने के लिए, यह सी ++ मानक द्वारा लागू नहीं किया गया है)।

बहुत सारे हेडर शामिल करने से आपके बाइनरी आकार में भी वृद्धि नहीं होगी (लेकिन यह आपके संकलन का समय, सीएफएफ, पूर्व-कॉम्प्लेटेड हेडर) में वृद्धि कर सकता है। कुछ अपवाद वैश्विक वस्तुओं और गतिशील पुस्तकालयों (जो छीन नहीं किए जा सकते हैं) के लिए खड़े हैं। मैं भी कई खंडों में कोड को अलग करने के बारे में इस मार्ग ( जीसीसी केवल ) को पढ़ने की सलाह देता हूं।

प्रदर्शन के बारे में एक आखिरी नोटिस: यदि आप बहुत सारे परस्पर आश्रित कोड का उपयोग करते हैं (यानी कोड जो रिश्तेदार offsets के साथ किसी भी पते पर मैप नहीं कर सकता, लेकिन किसी स्थानांतरित या समान तालिका के माध्यम से कुछ 'हॉटपैचिंग' की ज़रूरत होती है) तो एक स्टार्टअप लागत होगी ।





linker