c++ - stroustrup - सी++ प्रोग्राम्स




वस्तु फ़ाइल और साझा वस्तु फ़ाइल के बीच संबंध (2)

साझा ऑब्जेक्ट ( .so ) फ़ाइल और ऑब्जेक्ट (। .o ) फाइल के बीच संबंध क्या है?

क्या आप कृपया उदाहरण के माध्यम से समझाएं?


ए तो खिड़कियों पर एक। Dll के अनुरूप है ए। ओ वास्तव में एक .obj के रूप में दृश्य स्टूडियो के अंतर्गत है


मान लीजिए आपके पास निम्न सी स्रोत फ़ाइल है, इसे name.c कॉल करें

#include <stdio.h>
#include <stdlib.h>

void print_name(const char * name)
{
    printf("My name is %s\n", name);
}

जब आप इसे संकलित करते हैं, तो cc name.c साथ आप name.o जेनरेट name.o .o में कंसाइल किए गए कोड और सभी फ़ंक्शंस और डेटा नामों में परिभाषित व्हेरिएबल्स शामिल हैं, साथ ही सूचकांक ने वास्तविक कोड के साथ उनके नामों को जोड़ लिया है। यदि आप उस इंडेक्स को देखते हैं, तो nm टूल (लिनक्स और कई अन्य यूनिक्सों पर उपलब्ध) के साथ कहें तो आपको दो प्रविष्टियों की सूचना मिलेगी:

00000000 T print_name
         U printf

इसका क्या मतलब है: .o में संग्रहीत दो प्रतीकों (फ़ंक्शन या वेरिएबल्स के नाम हैं, लेकिन कक्षाएं, स्ट्रैक्ट्स, या किसी भी प्रकार के नाम) नहीं हैं। सबसे पहले, T के साथ चिह्नित वास्तव में name.o में इसकी परिभाषा शामिल है दूसरे, U के साथ चिह्नित केवल एक संदर्भ हैprint_name के लिए कोड यहां मिल सकता है, लेकिन printf के लिए कोड नहीं कर सकता जब आपका वास्तविक कार्यक्रम चलाता है, तो उन सभी प्रतीकों को खोजना होगा जो सन्दर्भ और दूसरे ऑब्जेक्ट फाइलों में उनकी परिभाषाओं को देखने के लिए एक साथ पूरा प्रोग्राम या पूर्ण लाइब्रेरी में जुड़ें। इसलिए एक ऑब्जेक्ट फ़ाइल स्रोत फाइल में दी जाने वाली परिभाषा, बाइनरी फॉर्म में परिवर्तित हो जाती है, और पूर्ण प्रोग्राम में रखने के लिए उपलब्ध है।

आप एक साथ एक फाइल कर सकते हैं। एक साथ फाइल कर सकते हैं, लेकिन आप ऐसा नहीं करते हैं: आम तौर पर उनमें बहुत कुछ है, और वे एक कार्यान्वयन विवरण हैं। आप वास्तव में उन सभी को संबंधित वस्तुओं के बंडल में एकत्रित करना चाहते हैं, साथ ही अच्छी तरह से मान्यता प्राप्त नामों के साथ। इन बंडलों को पुस्तकालय कहा जाता है और वे दो रूपों में आते हैं: स्थैतिक और गतिशील

एक स्थैतिक लाइब्रेरी (यूनिक्स में) लगभग हमेशा के साथ। .a (उदाहरणों में लाइब्रेरी में सी सी लाइब्रेरी, libm.a जो सी गणित पुस्तकालय है) और इतने पर है। उदाहरण को जारी रखने के लिए कि आप ar rc libname.a name.o साथ अपनी स्थैतिक लाइब्रेरी का निर्माण ar rc libname.a name.oar rc libname.a name.o । यदि आप libname.a पर nm चलाते हैं तो आपको यह दिखाई देगा:

name.o:
00000000 T print_name
         U printf

जैसा कि आप देख सकते हैं कि मुख्य रूप से उस ऑब्जेक्ट फाइल की एक बड़ी तालिका होती है, जिसमें उसमें सभी नाम मिलते हैं। ऑब्जेक्ट फ़ाइलों की तरह ही प्रत्येक .o और उनके द्वारा निर्दिष्ट प्रतीकों में परिभाषित दोनों प्रतीकों में शामिल हैं। यदि आप किसी अन्य .o में लिंक करना चाहते थे (जैसे date.o पर print_date ), तो आप ऊपर एक जैसे अन्य एंट्री देखेंगे।

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

एक गतिशील या साझा लाइब्रेरी । के साथ suffixed है। यह, इसकी स्थिर एनालॉग की तरह, ऑब्जेक्ट फाइलों की एक बड़ी तालिका है, जो संकलित सभी कोड का संदर्भ देती है। आप इसे cc -shared libname.so name.o साथ cc -shared libname.so name.onm साथ खोजना हालांकि स्थैतिक पुस्तकालय की तुलना में थोड़ा अलग है। मेरे सिस्टम में इसमें दो दर्जन प्रतीकों में से केवल दो print_name और printf :

00001498 a _DYNAMIC
00001574 a _GLOBAL_OFFSET_TABLE_
         w _Jv_RegisterClasses
00001488 d __CTOR_END__
00001484 d __CTOR_LIST__
00001490 d __DTOR_END__
0000148c d __DTOR_LIST__
00000480 r __FRAME_END__
00001494 d __JCR_END__
00001494 d __JCR_LIST__
00001590 A __bss_start
         w [email protected]@GLIBC_2.1.3
00000420 t __do_global_ctors_aux
00000360 t __do_global_dtors_aux
00001588 d __dso_handle
         w __gmon_start__
000003f7 t __i686.get_pc_thunk.bx
00001590 A _edata
00001594 A _end
00000454 T _fini
000002f8 T _init
00001590 b completed.5843
000003c0 t frame_dummy
0000158c d p.5841
000003fc T print_name
         U [email protected]@GLIBC_2.0

साझा लाइब्रेरी एक स्थिर लाइब्रेरी से बहुत ही महत्वपूर्ण तरीके से अलग होती है: यह आपके अंतिम निष्पादन योग्य में ही एम्बेड नहीं करता है। इसके बजाय निष्पादन योग्य में साझा किए गए लाइब्रेरी का एक संदर्भ होता है, जिसे लिंक समय पर नहीं बल्कि रन-टाइम पर हल किया जाता है। इसके कई फायदे हैं:

  • आपके निष्पादन योग्य बहुत छोटा है यह केवल उस ऑब्जेक्ट फ़ाइलों के माध्यम से आपके द्वारा स्पष्ट रूप से लिंक किए गए कोड शामिल हैं बाहरी पुस्तकालय संदर्भ हैं और उनका कोड बाइनरी में नहीं जाता है।
  • आप एकाधिक निष्पादनयोग्य के बीच एक पुस्तकालय के बिट्स (इसलिए नाम) साझा कर सकते हैं
  • आप, यदि आप द्विआधारी अनुकूलता के बारे में सावधान कर रहे हैं, कार्यक्रम के रन के बीच पुस्तकालय में कोड को अपडेट कर सकते हैं, और प्रोग्राम आपको इसे बदलने की आवश्यकता के बिना नई लाइब्रेरी ले जाएगा।

कुछ नुकसान हैं:

  • एक कार्यक्रम को एक साथ जोड़ने के लिए समय लगता है साझा लाइब्रेरी के साथ इस समय के कुछ निष्पादन योग्य रनों को हर समय स्थगित कर दिया जाता है।
  • प्रक्रिया अधिक जटिल है साझा पुस्तकालय में सभी अतिरिक्त प्रतीकों को समय-समय पर पुस्तकालय लिंक करने के लिए आवश्यक बुनियादी ढांचे का हिस्सा हैं।
  • पुस्तकालय के भिन्न संस्करणों के बीच सूक्ष्म असंगतिओं के जोखिम को आप चलाते हैं। विंडोज़ में इसे "डीएलएल नरक" कहा जाता है

(यदि आप इसके बारे में सोचते हैं, तो इनमें से कई कारणों से कारण होते हैं कि कार्यक्रमों का उपयोग अन्य वर्गों में सीधे एक कक्षा के ऑब्जेक्ट्स को सीधे एम्बेड करने के बजाय संदर्भों और संकेतों का उपयोग करते हैं। सादृश्य बहुत सीधा है।)

ठीक है, यह बहुत अधिक विस्तार है, और मैंने बहुत कुछ छोड़ा है, जैसे कि लिंकिंग प्रक्रिया वास्तव में कैसे काम करती है मुझे आशा है कि आप इसका अनुसरण कर सकते हैं। अगर स्पष्टीकरण के लिए नहीं पूछना







object-files