2009-02-26 10 views
31

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

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

हालांकि, इस बिंदु पर जाने के लिए मुझे कई दिनों तक खिड़कियों से लड़ना पड़ा, मैनिफेस्ट फाइलों और पुनर्वितरण योग्य पैकेजों के बारे में सब कुछ सीखना पड़ा।

जहां तक ​​मेरी समझ जाता है:

वी.एस. 2005 के साथ, माइक्रोसॉफ्ट साइड DLLs के द्वारा बनाई गई साइड। इसके लिए प्रेरणा यह है कि पहले, कई अनुप्रयोग एक ही डीएलएल के विभिन्न संस्करण स्थापित करेंगे, जिससे पहले स्थापित और काम करने वाले अनुप्रयोगों को क्रैश करने के लिए (यानी "डीएल नरक") उत्पन्न होता है। साइड डीएलएस द्वारा साइड इसे ठीक करें, क्योंकि अब प्रत्येक निष्पादन योग्य/डीएल में संलग्न "मेनिफेस्ट फ़ाइल" है जो निर्दिष्ट करता है कि कौन सा संस्करण निष्पादित किया जाना चाहिए।

यह सब ठीक है और अच्छा है। आवेदन अब रहस्यमय ढंग से दुर्घटनाग्रस्त नहीं होना चाहिए। हालांकि ...

माइक्रोसॉफ्ट विजुअल स्टूडियो की हर रिलीज के साथ सिस्टम डीएलएस का एक नया सेट जारी करता प्रतीत होता है। साथ ही, जैसा कि मैंने पहले उल्लेख किया था, मैं एक डेवलपर हूं जो किसी तृतीय पक्ष लाइब्रेरी से लिंक करने का प्रयास कर रहा है। अक्सर, इन चीजों को "precompiled डीएल" के रूप में वितरित किया जाता है। अब, क्या होता है जब दृश्य स्टूडियो के एक संस्करण के साथ संकलित एक प्रीकंपिल्ड डीएल दृश्य स्टूडियो के दूसरे संस्करण का उपयोग कर किसी एप्लिकेशन से जुड़ा होता है?

जो मैंने इंटरनेट पर पढ़ा है, उससे खराब चीजें होती हैं। सौभाग्य से, मुझे अब तक कभी नहीं मिला - मैं निष्पादन योग्य चलाने पर "MSVCR80.dll नहीं मिला" समस्या में भाग रहा था और इस प्रकार मैंने इस पूरे मैनिफेस्ट मुद्दे में अपना प्रयास शुरू किया।

मैं अंततः निष्कर्ष पर आया कि इसे काम करने के लिए एकमात्र तरीका (स्थिर रूप से सब कुछ जोड़ने के अलावा) यह है कि सभी तृतीय पक्ष पुस्तकालयों को विजुअल स्टूडियो के समान संस्करण का उपयोग करके संकलित किया जाना चाहिए - यानी प्रीकंपील्ड डीएलएस का उपयोग न करें - स्रोत डाउनलोड करें, एक नया डीएलएल बनाएं और इसके बजाए इसका इस्तेमाल करें।

क्या यह वास्तव में सच है? क्या मैं कुछ भुल गया?

इसके अलावा, यदि ऐसा लगता है, तो मैं मदद नहीं कर सकता लेकिन सोचता हूं कि माइक्रोसॉफ्ट ने घृणित कारणों से यह किया है।

न केवल सभी प्रीकंपील्ड बाइनरी को तोड़ने में अनावश्यक रूप से मुश्किल होती है, यदि आप एक ऐसी सॉफ्टवेयर कंपनी के लिए काम करते हैं जो तीसरे पक्ष के स्वामित्व पुस्तकालयों का उपयोग करता है, तो जब भी वे विजुअल स्टूडियो के नवीनतम संस्करण में अपग्रेड करते हैं - आपकी कंपनी को अब वही काम करना होगा या कोड अब नहीं चलेंगे।

एक तरफ, लिनक्स इस से कैसे बचता है? हालांकि मैंने कहा कि मैं इसे विकसित करना पसंद करता हूं और मैं लिंकिंग के यांत्रिकी को समझता हूं, मैंने इस तरह के निम्न स्तर के साझा पुस्तकालयों की समस्या को हल करने के लिए पर्याप्त लंबे समय तक कोई भी अनुप्रयोग नहीं बनाए रखा है।

अंत में, समेकित करने के लिए: क्या इस नई मेनिफेस्ट योजना के साथ प्रीकंपील्ड बाइनरी का उपयोग करना संभव है? यदि यह है, तो मेरी गलती क्या थी? यदि ऐसा नहीं है, तो माइक्रोसॉफ्ट ईमानदारी से सोचता है कि यह एप्लिकेशन विकास को आसान बनाता है?

अपडेट - एक और संक्षिप्त प्रश्न: लिनक्स मेनिफेस्ट फ़ाइलों के उपयोग से कैसे बचता है?

+0

मुझे समझ में नहीं आ रहा है कि इस सवाल को क्यों वोट दिया गया है ... ऐसा लगता है कि ... और थोड़ी सी माइक्रोसॉफ्ट निराशा से अच्छी तरह से परेशान, अच्छी तरह से निराश और तर्क के लिए तैयार है। – Beska

+0

मुझे लगता है कि यह पढ़ने के लिए बहुत सारे पाठ है! यदि सवाल अधिक संक्षिप्त था तो उसे बेहतर भाग्य हो सकता है। –

+0

जब कोई प्रश्न का शीर्षक पूछता है "क्या एक्स बुराई की कोशिश कर रहा है?" जब लोग इसे कम करते हैं तो आश्चर्यचकित न हों। :) – bk1e

उत्तर

26

आपके आवेदन में सभी घटक साझा करना चाहिए एक ही रनटाइम। जब यह मामला नहीं है, तो आप हटाए गए वक्तव्यों पर जोर देने जैसी अजीब समस्याओं में भाग लेते हैं।

यह सभी प्लेटफ़ॉर्म पर समान है। माइक्रोसॉफ्ट का आविष्कार ऐसा कुछ नहीं है।

आप इस 'केवल एक रनटाइम' समस्या के आसपास हो सकते हैं, यह जानकर कि रनटाइम वापस काट सकता है। यह ज्यादातर उन मामलों में है जहां आप एक मॉड्यूल में स्मृति आवंटित करते हैं, और इसे दूसरे में मुक्त करते हैं।

a.dll 
    dllexport void* createBla() { return malloc(100); } 

b.dll 
    void consumeBla() { void* p = createBla(); free(p); } 

a.dll और b.dll अलग rumtimes से जुड़े होते हैं, तो यह दुर्घटनाओं, क्योंकि क्रम कार्यों को अपने स्वयं के ढेर को लागू।

आप आसानी से इस समस्या से बच सकते हैं जिसे नष्टबला फ़ंक्शन प्रदान करके स्मृति को मुक्त करने के लिए कहा जाना चाहिए।

ऐसे कई मुद्दे हैं जहां आप रनटाइम के साथ समस्याओं में भाग ले सकते हैं, लेकिन इन संरचनाओं को लपेटकर अधिकांश से बचा जा सकता है।

संदर्भ के लिए:

  • आवंटित नहीं है/मुक्त स्मृति/वस्तुओं मॉड्यूल सीमाओं के पार
  • अपने dll इंटरफ़ेस में जटिल वस्तुओं का उपयोग नहीं करते। (उदाहरण के लिए std :: string, ...)
  • डीएल सीमाओं में विस्तृत सी ++ तंत्र का उपयोग न करें। (Typeinfo, सी ++ अपवाद, ...)
  • ...

लेकिन यह प्रकट होता है के साथ एक समस्या नहीं है।

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

तो अपने एप्लिकेशन का उपयोग करने से पहले अपना रनटाइम इंस्टॉल करें, और आपको 'लापता निर्भरता' त्रुटि नहीं मिलेगी।


(पर अपडेट किया गया सवाल "कैसे लिनक्स प्रकट फ़ाइलों के उपयोग से बचने करता है")

मालसूची फ़ाइल क्या है?

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

यह डीएल के विशिष्ट संस्करण को निर्दिष्ट करके किया जाता है जो ऐप/लोडिंग निर्भरताओं को शुरू करते समय लोड किया जाना है।

ऐसा क्यों किया जाता है (कई अन्य चीजें आप प्रकट फ़ाइलें, जैसे कुछ मेटा डेटा यहां रखा जा सकता है के साथ कर सकते हैं)?

संस्करण ऐतिहासिक कारणों से डीएलएल नाम का हिस्सा नहीं है। तो "comctl32.dll" इस तरह के सभी संस्करणों में इस तरह से नामित किया गया है। (तो Win2k के तहत comctl32 XP या Vista में से एक से अलग है)। यह निर्दिष्ट करने के लिए कि आप वास्तव में कौन सा संस्करण चाहते हैं (और इसके खिलाफ परीक्षण किया है), आप संस्करण की जानकारी "appname.exe.manifest" फ़ाइल में रखें (या इस फ़ाइल/जानकारी को एम्बेड करें)।

ऐसा क्यों किया गया था?

कई कार्यक्रम systemrootdir पर system32 निर्देशिका में अपने dlls स्थापित किया। यह सभी निर्भर अनुप्रयोगों के लिए आसानी से साझा पुस्तकालयों को साझा करने के लिए बगफिक्स को अनुमति देने के लिए किया गया था। और सीमित स्मृति के दिनों में, साझा पुस्तकालयों ने स्मृति पदचिह्न को कम कर दिया जब कई अनुप्रयोगों ने समान पुस्तकालयों का उपयोग किया।

इस अवधारणा का दुरुपयोग कई प्रोग्रामर द्वारा किया गया था, जब उन्होंने अपने सभी डीएलएस को इस निर्देशिका में स्थापित किया था; कभी-कभी पुराने लोगों के साथ साझा पुस्तकालयों के नए संस्करणों को ओवरराइट करना। कभी-कभी पुस्तकालय अपने व्यवहार में चुपचाप बदल जाते हैं, ताकि निर्भर अनुप्रयोग दुर्घटनाग्रस्त हो जाएं।

यह "एप्लिकेशन निर्देशिका में सभी डीएलएस वितरित करने" के दृष्टिकोण की ओर ले जाता है।

यह बुरा क्यों था?

जब बग दिखाई दी, तो कई निर्देशिकाओं में बिखरे हुए सभी डीएलएस को अद्यतन किया जाना था। (Gdiplus.dll) अन्य मामलों इस नहीं था भी संभव (विंडोज़ घटक) में

प्रकट दृष्टिकोण

यह दृष्टिकोण से ऊपर सभी समस्याओं को हल करती है। आप डीएलएस को केंद्रीय स्थान पर इंस्टॉल कर सकते हैं, जहां प्रोग्रामर हस्तक्षेप नहीं कर सकता है। यहां डीएलएस अपडेट किए जा सकते हैं (WinSxS फ़ोल्डर में डीएलएल अपडेट करके) और लोडर 'दाएं' डीएलएल लोड करता है। (संस्करण मिलान डीएलएल लोडर द्वारा किया जाता है)।

लिनक्स में यह मैकेनिक क्यों नहीं है?

मेरे पास कई अनुमान हैं। क्योंकि वहाँ केवल एक ही 'क्रम' है लक्षित दर्शकों

  • के लिए एक गैर मुद्दा (यह वास्तव में सिर्फ अनुमान लगा है ...)

    • अधिकांश चीजें, खुला स्रोत हैं, इसलिए एक बग सुधार के लिए फिर कंपाइल (जीसीसी रनटाइम), रनटाइम शेयरिंग/लाइब्रेरी सीमाओं के साथ समस्या इतनी बार नहीं होती है
    • कई घटक इंटरफ़ेस स्तर पर सी का उपयोग करते हैं, जहां ये समस्याएं तब होती हैं जब सही हो तो
    • पुस्तकालयों का संस्करण सबसे अधिक है इसकी फाइल के नाम पर एम्बेडेड मामले।
    • अधिकांश एप्लिकेशन स्थिर रूप से उनके पुस्तकालयों से बंधे होते हैं, इसलिए कोई भी डीएल-नरक नहीं हो सकता है।
    • जीसीसी रनटाइम बहुत एबीआई स्थिर रखा गया था ताकि ये समस्याएं न हो सकें।
  • +0

    आपका क्या मतलब है कि उन्हें एक ही रनटाइम साझा करना होगा? मुझे लगता है कि लिनक्स में, सभी साझा वस्तुओं को एक ही मानक सी lib से लिंक करना चाहिए, और मुझे नहीं पता कि अगर ऐसा नहीं होता तो क्या होगा। हालांकि, मैनिफेस्ट फाइलें एक संपूर्ण माइक्रोस्कोफ्ट "आविष्कार" हैं जो कुछ हद तक अनावश्यक लगती हैं। मेरी टिप्पणियां अब – Voltaire

    +0

    'अलग-अलग रनटाइम्स' का अर्थ आम तौर पर "डीबग या रिलीज़" का मतलब है। मेमोरी आवंटक अलग हैं, इसलिए a.dll में alloc, b.dll को स्मृति पास करें यदि वे अलग हैं तो आपके ऐप को क्रैश कर देगा। समाधान हमेशा एक ही डीएल में एमएम आवंटित और मुक्त करने के लिए है। तब आपको कोई समस्या नहीं है। – gbjbaanb

    +4

    ** (लिनक्स में यह मैकेनिक क्यों नहीं है?) ** लिनक्स ईएलएफ का उपयोग करता है जो संस्करण की जानकारी संग्रहीत करता है। यदि आप लाइब्रेरी के संस्करण 2.2 का उपयोग करते हैं तो आपका प्रोग्राम 2.3 के साथ चलता है लेकिन बस 2.1 या 3.0 के साथ बाहर निकलता है। 2002 के बाद से प्रत्येक व्यक्ति केवल पीछे की ओर-संगत परिवर्तनों के साथ संगत सी रनटाइम (ग्लिब/ईग्लिब) का उपयोग करता है। स्टेटिक लिंकिंग बेहद असामान्य है। लाइब्रेरी विक्रेता परिवर्तनों के बारे में सावधान हैं, और डीएलएल नरक को डिस्ट्रो रखरखावकर्ताओं द्वारा निपटाया जाता है, सिसडमिन नहीं। सी ++ एबीआई परिवर्तन एक दर्द था लेकिन यह खत्म हो गया है। जब जीटीके 3.0 आता है तो यह जीटीके 2.0 के साथ स्थापित किया जाएगा, इसलिए दोनों के लिए ऐप्स ठीक चलेंगे। –

    1

    मैं अंत में निष्कर्ष पर पहुंचा कि एक ही रास्ता यह काम करने के लिए (के अलावा स्थिर सब कुछ जोड़ने) प्राप्त करने के लिए है कि सभी तृतीय पक्ष लाइब्रेरी दृश्य स्टूडियो के एक ही संस्करण का उपयोग कर संकलित किया जाना चाहिए - यानी उपयोग नहीं करते precompiled डीएलएस - स्रोत डाउनलोड करें, एक नया डीएलएल बनाएँ और इसके बजाय इसका उपयोग करें।

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

    ... जैसा कि मैं इसे समझता हूं। :)

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

    +1

    स्थिर लिंकिंग क्यों सुरक्षित है? मान लीजिए कि तृतीय पक्ष डीएलएल स्थिर रूप से वीसी 8 और आपके डीएलएल को वीसी 9 से लिंक करने के लिए लिंक कर रहा है, तो आप तीसरे पेट्री डीएलएल में बनाए गए अपने डीएलएल में किसी ऑब्जेक्ट को हटाने का प्रयास करते हैं, तो क्या होगा? –

    +0

    @lzprgmr: यह नहीं है, और - का-ब्लैमो! – Spike0xff

    +0

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

    3

    एक तीसरी पार्टी DLL स्मृति और आप यह मुक्त करने की आवश्यकता पर आवंटित करेगा, तो आप एक ही रन-टाइम पुस्तकालयों की जरूरत है। यदि डीएलएल ने कार्यों को आवंटित और हटा दिया है, तो यह ठीक हो सकता है।

    यह तीसरा पक्ष डीएलएल std कंटेनर का उपयोग करता है, जैसे कि vector, आदि। आपको समस्याएं हो सकती हैं क्योंकि ऑब्जेक्ट्स का लेआउट पूरी तरह अलग हो सकता है।

    चीजें काम करने के लिए संभव है, लेकिन कुछ सीमाएं हैं। मैंने ऊपर सूचीबद्ध दोनों समस्याओं में भाग लिया है।

    +0

    क्यों std कंटेनरों का उपयोग स्मृति लेआउट अलग का कारण बनता है? –

    +1

    यह कोड इंटरफ़ेस stl का उपयोग करता है, फिर हाँ! वीसी 6 एसडीडी कंटेनरों को वीएस -2008 एसडीडी से अलग कोड किया गया है जो दोनों एसटीएलपोर्ट से अलग हैं। डीएल के संकलित कोड में एक परिभाषा है, लेकिन आपका कोड जिसमें उनके शीर्षलेख शामिल हैं, फिर उस कोड को अलग-अलग संकलित करते हैं। मेरा विश्वास करो, मैंने इसे देखा है। – crashmstr

    3

    यदि कोई तृतीय पक्ष डीएलएल स्मृति को आवंटित करता है जिसे आपको मुक्त करने की आवश्यकता होती है, तो डीएलएल ने प्रीकंपिल्ड डीएलएल के शिपिंग के प्रमुख नियमों में से एक तोड़ दिया है। इस कारण से बिल्कुल।

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

    संबंधित मुद्दे