क्या C ++ 11 पता गतिशील / साझा पुस्तकालय सीमाओं के बीच एसटीडी काम की वस्तुओं को पारित करने से संबंधित है? (यानी dlls और इतने पर)?


34

C ++ के बारे में मेरी एक बड़ी शिकायत यह है कि डायनैमिक लाइब्रेरी (यानी dll / so) सीमाओं के बाहर std लाइब्रेरी ऑब्जेक्ट्स को पास करना कितना मुश्किल है।

एसटीडी लाइब्रेरी अक्सर हेडर-ओनली होती है। जो कुछ भयानक अनुकूलन करने के लिए महान है। हालाँकि, dll के लिए, वे अक्सर विभिन्न संकलक सेटिंग्स के साथ निर्मित होते हैं जो आंतरिक संरचना / एक std लाइब्रेरी कंटेनरों के कोड को प्रभावित कर सकते हैं। उदाहरण के लिए, MSVC में एक dll itter डीबगिंग के साथ निर्माण कर सकता है जबकि दूसरा इसके साथ बनाता है। ये दो dll आसपास के std कंटेनरों को चलाने के मुद्दों में चल सकते हैं। यदि मैं std::stringअपने इंटरफ़ेस में उजागर करता हूं, तो मैं यह गारंटी नहीं दे सकता कि ग्राहक जिस कोड का उपयोग कर रहा std::stringहै वह मेरी लाइब्रेरी का सटीक मिलान है std::string

यह समस्याओं को दूर करने के लिए कठिन है, सिरदर्द, आदि। आप या तो सख्ती से इन मुद्दों को रोकने के लिए अपने संगठन में संकलक सेटिंग्स को नियंत्रित करते हैं या आप एक सरल सी इंटरफ़ेस का उपयोग करते हैं जिसमें ये समस्याएं नहीं होंगी। या अपने ग्राहकों को अपेक्षित संकलक सेटिंग्स का उपयोग करने के लिए निर्दिष्ट करें जो उन्हें उपयोग करना चाहिए (जो बेकार है यदि कोई अन्य पुस्तकालय संकलक सेटिंग्स निर्दिष्ट करता है)।

मेरा सवाल यह है कि इन मुद्दों को हल करने के लिए C ++ 11 ने कुछ करने की कोशिश की या नहीं?


3
मुझे आपके प्रश्न का उत्तर नहीं पता है, लेकिन मैं कह सकता हूं कि आपकी चिंताओं को साझा किया गया है; वे अपनी परियोजनाओं में C ++ का उपयोग क्यों नहीं करेंगे, इसकी एक प्रमुख क्षमता है, क्योंकि हम संभावित दक्षता के प्रत्येक अंतिम चक्र को निचोड़ने पर ABI स्थिरता को महत्व देते हैं।
डोना फेलो

2
कृपया भेद करें। यह मुश्किल है DLLएस के बीच । SOएस के बीच यह हमेशा ठीक काम करता था।
Jan Hudec

1
कड़ाई से बोलना, यह सी ++ केवल समस्या नहीं है। अन्य भाषाओं के साथ यह समस्या होना संभव है।
MrFox

2
@JanHudec मैं गारंटी दे सकता हूं कि SO के बीच लगभग इतने जादुई तरीके से काम नहीं होता जितना आप इंगित करते हैं। प्रतीक दृश्यता को देखते हुए और नाम का उपयोग अक्सर कैसे काम करता है, आप एक समस्या से अधिक अछूते हो सकते हैं, लेकिन किसी एक .so को किसी भी झंडे / आदि के साथ संकलित करना, और यह मानकर कि आप इसे अन्य झंडों के साथ एक कार्यक्रम में जोड़ सकते हैं आपदा के लिए एक प्राप्तकर्ता है।
एसडीजी

3
@ एसडीजी: डिफ़ॉल्ट झंडे और डिफ़ॉल्ट दृश्यता के साथ यह काम करता है। यदि आप उन्हें बदलते हैं और परेशानी में पड़ते हैं, तो यह आपकी समस्या है और किसी और की नहीं।
Jan Hudec

जवाबों:


20

आप सही हैं कि एसटीएल - वास्तव में, किसी भी तीसरे पक्ष के पुस्तकालय से कुछ भी जो अस्थायी है - किसी भी सार्वजनिक सी ++ एपीआई में सबसे अच्छा बचा जाता है। आप ABI के टूटने को रोकने के लिए http://www.ros.org/reps/rep-0009.html#definition पर नियमों की लंबी सूची का पालन करना चाहते हैं, जो प्रोग्रामिंग को सार्वजनिक बनाता है C ++ API एक कोर।

और C ++ 11 के संबंध में उत्तर नहीं है, यह मानक ऐसा नहीं है। अधिक दिलचस्प क्यों नहीं है? इसका कारण यह है कि C ++ 17 बहुत अधिक छू रहा है, और C ++ मॉड्यूल को लागू करने के लिए हमें काम करने के लिए निर्यात किए गए टेम्पलेट्स की आवश्यकता है, और इसके लिए हमें एक LLVM प्रकार के संकलक की आवश्यकता है जैसे कि क्लैंग जो डिस्क को पूर्ण एएसटी को डंप कर सकता है और फिर किसी भी बड़ी सी ++ परियोजना में कई ओडीआर उल्लंघन के मामलों को संभालने के लिए कॉलर-निर्भर लुकअप करते हैं - जो, वैसे, बहुत सारे जीसीसी और ईएलएफ कोड शामिल हैं।

अंत में, मुझे बहुत सारे MSVC नफरत और समर्थक GCC टिप्पणियां दिखाई देती हैं। ये बहुत गलत हैं - ELF पर GCC मौलिक रूप से, और अनियमित रूप से, वैध और सही C ++ कोड का उत्पादन करने में असमर्थ है। इसके कारण कई हैं और किंवदंतियां हैं, लेकिन मैं जल्दी से एक मामले का उदाहरण दूंगा: ईएलएफ पर जीसीसी सुरक्षित रूप से Boost.Python का उपयोग करके लिखे गए पायथन एक्सटेंशन का उत्पादन नहीं कर सकता है जहां Boost.Python पर आधारित एक से अधिक एक्सटेंशन अजगर में लोड है। ऐसा इसलिए है क्योंकि इसकी वैश्विक सी प्रतीक तालिका के साथ ईएलएफ केवल ओडीआर उल्लंघन को रोकने के डिजाइन के कारण अक्षम है, जबकि पीई और माचो और वास्तव में प्रस्तावित सी ++ मॉड्यूल विनिर्देश सभी प्रति-मॉड्यूल प्रतीक तालिकाओं का उपयोग करते हैं - जो संयोगवश बहुत तेजी से init बार भी तेज प्रक्रिया है। और बहुत अधिक समस्याएं हैं: एक स्टैकऑवरफ्लो देखें जिसका मैंने हाल ही में जवाब दियाhttps://stackoverflow.com/questions/14268736/symbol-visibility-exception-runtime-error/14364055#14364055 उदाहरण के लिए जहाँ C ++ अपवाद फेंकता ELF पर बेहद मौलिक रूप से टूटे हुए हैं।

अंतिम बिंदु: अलग-अलग एसटीएल के बीच अंतर करने के बारे में, यह कई बड़े कॉर्पोरेट उपयोगकर्ताओं के लिए एक बड़ी पीड़ा है जो तीसरे पक्ष के पुस्तकालयों को मिलाने की कोशिश कर रहे हैं जो कसकर कुछ एसटीएल कार्यान्वयन के लिए एकीकृत हैं। एकमात्र समाधान ST ++ इंटरॉप को संभालने के लिए C ++ का एक नया तंत्र है, और जब वे इस पर होते हैं तो आप कंपाइलर इंटरॉप को भी ठीक कर सकते हैं ताकि आप (उदाहरण के लिए) MSVC, GCC और क्लैग संकलित ऑब्जेक्ट फ़ाइलों को मिला सकें और यह सब काम करता है । मैं C ++ 17 प्रयास देखता हूँ और देखता हूँ कि अगले कुछ वर्षों में वहाँ क्या होता है - मुझे आश्चर्य होगा अगर कुछ नहीं करता है।


शानदार प्रतिक्रिया! मुझे केवल आशा है कि क्लैंग विंडोज़ संगतता में सुधार करता है, और यह एक अच्छा डिफ़ॉल्ट मानक संकलक सेट कर सकता है। C ++ का शाब्दिक समावेश / हेडर सिस्टम भयानक है, मैं उस दिन की प्रतीक्षा कर रहा हूं, जो मॉड्यूल C ++ कोड संगठन को सरल करता है, अनन्त रूप से संकलन समय को गति देता है, और ODR- उल्लंघन करने वाले कैच के साथ कंपाइलर इंटरऑपरेबिलिटी में सुधार करता है।
एलेसेंड्रो स्टैमैटो

3
व्यक्तिगत रूप से, मैं वास्तव में कंपाइलर समय में पर्याप्त वृद्धि की उम्मीद कर रहा हूं । इंट्रा-मॉड्यूल एएसटी को जल्दी से निकालना बहुत कठिन है, और हमें संभवतः इसके लिए एक मेमोरी साझा मेमोरी कैश की आवश्यकता होगी। हालांकि, लगभग सब कुछ जो बुरा है वह बेहतर हो जाता है। बीटीडब्लू, हेडर फाइलें निश्चित रूप से आसपास रहती हैं, वर्तमान सी ++ मॉड्यूल में हेडर फाइलों के लिए 1 से लेकर 1 तक की इंटरफेस फाइलें हैं। इसके अलावा, ऑटो-जेनरेट की गई इंटरफ़ेस फाइल्स कानूनी C ++ होगी, इसलिए एक विरासत हेडर को C मैक्रोज़ को फ़िल्टर करने और इंटरफ़ेस फ़ाइलों के रूप में बाहर निकालने की अनुमति मिलती है। अच्छा लगा ना?
नियाल डगलस

ठंडा! मुझे मॉड्यूल के बारे में बहुत सारे संदेह हैं। क्या मॉड्यूल प्रणाली पाठीय समावेश बनाम प्रतीकात्मक समावेश को ध्यान में रखेगी? वर्तमान के साथ संकलक में संकलक को हर स्रोत फ़ाइल के लिए बार-बार कोड की हजारों लाइनों की दसियों को फिर से जोड़ना होगा। क्या मॉड्यूल प्रणाली आगे की घोषणाओं के बिना किसी दिन कोड की अनुमति देगा? क्या यह उपकरण निर्माण में सुधार / सुगमता लाएगा?
एलेसेंड्रो स्टैमैटो

2
-1 के सुझाव के लिए कि सभी तृतीय-पक्ष टेम्पलेट संदिग्ध हैं। कॉन्फ़िगरेशन बदलना इस बात से स्वतंत्र है कि क्या कॉन्फ़िगर की जा रही चीज़ एक टेम्प्लेट है।
डेडजैम

1
@ एलेसैंड्रो: प्रस्तावित सी ++ मॉड्यूल स्पष्ट रूप से सी मैक्रोज़ को निष्क्रिय कर देता है। आप टेम्प्लेट, या Nowt का उपयोग कर सकते हैं। प्रस्तावित इंटरफेस कानूनी C ++ हैं, केवल ऑटोगेन्जेनेटेड हैं, और रिपार्सिंग की गति के लिए वैकल्पिक रूप से precompiled जा सकता है अर्थात मौजूदा precompiled हेडर पर किसी भी स्पीडअप की अपेक्षा नहीं करता है। अंतिम दो प्रश्न, मुझे वास्तव में नहीं पता है: यह निर्भर करता है :)
नियाल डगलस

8

विनिर्देशन में कभी भी यह मुद्दा नहीं था। ऐसा इसलिए है क्योंकि इसमें "वन डेफिनिशन रूल" नामक अवधारणा है, जो यह बताता है कि प्रत्येक प्रतीक की रनिंग प्रक्रिया में एक ही परिभाषा है।

Windows DLL इस आवश्यकता का उल्लंघन करते हैं। इसलिए ये सभी समस्याएं हैं। इसलिए इसे ठीक करना Microsoft के लिए है, C ++ मानकीकरण समिति नहीं। यूनिक्स में यह समस्या कभी नहीं थी, क्योंकि साझा पुस्तकालय अलग-अलग तरीके से काम करते हैं और डिफ़ॉल्ट रूप से एक परिभाषा नियम के अनुसार (आप स्पष्ट रूप से इसे तोड़ सकते हैं, लेकिन आप स्पष्ट रूप से केवल तभी करते हैं जब आप जानते हैं कि आप इसे बर्दाश्त कर सकते हैं और कुछ अतिरिक्त चक्रों को निचोड़ने की आवश्यकता है)।

Windows DLL एक परिभाषा नियम का उल्लंघन करता है क्योंकि:

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

ईएलएफ प्रारूप निर्यात का उपयोग करने वाला यूनिक्स पहली समस्या से बचने के लिए सभी निर्यात किए गए प्रतीकों का आयात करता है और दूसरे से बचने के लिए स्टेटिक लिंक समय तक सांख्यिकीय और गतिशील रूप से हल किए गए प्रतीकों के बीच अंतर नहीं करता है।


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


2
@ डग। जीसीसी का इससे कोई लेना-देना नहीं है। मंच ABI के पास है। ईएलएफ में, अधिकांश यूनियनों द्वारा उपयोग किए जाने वाले ऑब्जेक्ट प्रारूप, साझा पुस्तकालय सभी दृश्य प्रतीकों का निर्यात करते हैं और वे सभी प्रतीकों को निर्यात करते हैं जो वे निर्यात करते हैं। इसलिए यदि कई पुस्तकालयों में कुछ उत्पन्न होता है, तो डायनेमिक लिंकर सभी के लिए पहली परिभाषा का उपयोग करेगा। सरल, सुरुचिपूर्ण और काम कर रहे हैं।
Jan Hudec

1
@MartinBa: विलय करने के लिए कुछ भी नहीं है, लेकिन यह तब तक मायने नहीं रखता है जब तक यह एक ही है और जब तक यह पहली जगह में विलय नहीं किया जाता है। हां, यदि आप ईएलएफ प्लेटफॉर्म पर असंगत संकलक सेटिंग्स का उपयोग करते हैं, तो आपको कहीं भी और हर जगह समान गड़बड़ मिलती है। यहां तक ​​कि अगर साझा पुस्तकालयों का उपयोग नहीं किया जाता है, तो यह कुछ हद तक विषय है।
जन हडेक

1
@ जान - यह आपके उत्तर के लिए प्रासंगिक है। आप लिखते हैं: "... एक परिभाषा नियम ... विंडोज DLL इस आवश्यकता का उल्लंघन करते हैं ... साझा लाइब्रेरी अलग तरह से [UNix पर] काम करती हैं ..." लेकिन सवाल std-lib सामान (हेडर में परिभाषित) के साथ समस्याओं से संबंधित है और इसका कारण यह है कि यूनिक्स पर कोई समस्या नहीं है, इसलिए एसओ बनाम डीएलएल से कोई लेना-देना नहीं है, लेकिन इस तथ्य के साथ, कि यूनिक्स (जाहिरा तौर पर) में मानक पुस्तकालय का केवल एक ही संगत संस्करण है जबकि विंडोज एमएस पर असंगत (डिबग) संस्करण का चयन किया गया है (विस्तारित जाँच आदि के साथ)।
मार्टिन बा

1
@MartinBa: नहीं, विंडोज पर समस्या का मुख्य कारण यह है कि विंडोज पर उपयोग किया जाने वाला निर्यात / आयात तंत्र सभी मामलों में स्थिर सदस्यों और श्रेणी के प्रतिबाधा वर्ग को ठीक से मर्ज नहीं कर सकता है और सांख्यिकीय और गतिशील रूप से जुड़े प्रतीकों को मर्ज नहीं कर सकता है। यह कई लाइब्रेरी वेरिएंट द्वारा बहुत खराब बना दिया गया है, लेकिन प्राथमिक समस्या यह है कि सी ++ को लिंकर से लचीलेपन की आवश्यकता होती है जो विंडोज डायनेमिक लिंकर के पास नहीं है।
Jan Hudec

4
मुझे लगता है कि यह निहितार्थ कि DLL विनिर्देश टूट गया है और Msft के लिए 'इसे ठीक करने' की संबंधित मांग गलत है। यह तथ्य कि डीएलएल सी ++ की कुछ विशेषताओं का समर्थन नहीं करते हैं, डीएलएल विनिर्देश का दोष नहीं है। DLL एक भाषा-तटस्थ, विक्रेता-तटस्थ पैकेजिंग तंत्र और ABI में प्रवेश-बिंदुओं को मशीन कोड ('फ़ंक्शन कॉल') और डेटा ब्लॉब्स को उजागर करने के लिए हैं। वे कभी भी किसी विशेष भाषा की उन्नत सुविधाओं का मूल समर्थन नहीं करते थे। यह Msft, या DLL विनिर्देशन की गलती नहीं है कि कुछ लोग चाहते हैं कि वे कुछ और हों।
यूरो मिसेल

6

नहीं।

हैडर सिस्टम को बदलने के लिए बहुत काम चल रहा है, जिसे मॉड्यूल्स कहा जाता है और जिसका इस पर प्रभाव हो सकता है, लेकिन निश्चित रूप से यह एक बड़ा नहीं है।


2
मुझे नहीं लगता कि हेडर सिस्टम का इस पर कोई प्रभाव पड़ेगा। समस्या यह है कि विंडोज DLL एक परिभाषा नियम का उल्लंघन करते हैं (जिसका अर्थ है कि वे C ++ युक्ति का पालन नहीं करते हैं, इसलिए C ++ समिति इसके बारे में कुछ भी नहीं कर सकती है) और यह कि Windows में मानक रनटाइम के बहुत सारे वेरिएंट हैं, जो C ++ समिति ' t या तो कुछ भी करो।
जनवरी को

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

@PaMMichalik C ++ लिंकिंग (चरण 9) को कवर करता है और मुझे ऐसा लगता है कि DLL / SOs का कम से कम लोड-टाइम लिंकिंग चरण 9 के भीतर आता है। इसका मतलब है कि बाहरी लिंकेज (निर्यात या नहीं) के साथ प्रतीकों को जोड़ा जाना चाहिए और इसके अनुरूप होना चाहिए ODR LoadLibrary / dlopen के साथ गतिशील लिंकिंग स्पष्ट रूप से उन आवश्यकताओं के अंतर्गत नहीं आती है।
bames53

@ bames53: IMHO, चश्मा उस तरह के बयान की अनुमति देने के लिए बहुत कमजोर है। A .dll / .so को अपने दम पर "कार्यक्रम" के रूप में देखा जा सकता है। थान, नियम संतुष्ट थे। रन-टाइम पर अन्य "प्रोग्राम" लोड करने जैसा कुछ मानक के हिसाब से इतना कम है कि इस बारे में कोई भी बयान बहुत मनमाना है।
पॉल मिशालिक

@PaulMichalik यदि किसी निष्पादन योग्य को लोड-टाइम लिंकिंग की आवश्यकता होती है, तो लोड-टाइम लिंकिंग से पहले बाहरी निकाय अनसुलझे हैं और निष्पादन के लिए आवश्यक जानकारी गायब है। LoadLibrary और dlopen कल्पना के बाहर हैं, लेकिन बहुत स्पष्ट रूप से लिंक करने वाले लोड-टाइम को चरण 9 का हिस्सा होना चाहिए
bames53
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.