2009-01-20 15 views
5

मैं कैसे सुनिश्चित कर सकता हूं कि इसमें कोई ऑब्जेक्ट मौजूद नहीं है, जबकि कोई ऑब्जेक्ट अनलोड नहीं होता है?सी ++: डीएल अनलोडिंग समस्या

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

FlPtr यानी केवल सभी वस्तुओं के बाद अनलोड, एक सरल refrence गिनती वर्ग thats AddRef कॉल और आवश्यकतानुसार

ExampleDll *dll = LoadDll(L"bin\\example.dll"); 
IObject *obj = dll->CreateObject(); 
... 
obj->Release(); 
delete dll;//fine because all objects already deleted 
return 0; 

auto_ptr<ExampleDll> dll = LoadDll(L"bin\\example.dll"); 
FlPtr<IObject> obj = dll->CreateObject(); 
... 
return 0;//crash if dll is destructed before obj since Object::Release needs to call into the dll 

मैं dll संभाल itsself उतारने बनाने की कोशिश की रिलीज है हटा दिया गया है। यह एक नया ऑब्जेक्ट IExampleDll बनाकर काम करता है जो डीएल लागू करता है। यह पहले से exampleDll ऑब्जेक्ट की तरह है लेकिन exe के बजाए डीएल में रहता है और यह भी गिना जाता है। डीएल में प्रत्येक ऑब्जेक्ट इस विनाश पर इस प्रतिरक्षा को बढ़ाता है और विनाश पर इसे कम करता है। इसका मतलब है कि रिफ्रेंस गिनती केवल शून्य तक पहुंच जाती है जब एक्सई ने अपने रिफ्रेंस जारी किए हैं और सभी डीएलएस ऑब्जेक्ट्स नष्ट हो गए हैं। इसके बाद यह अपने विनाशक में फ्री लाइब्रेरी (GetModuleHandle()) को बुलाता है।

हालांकि यह FreeLibrary, im asuming पर दुर्घटनाओं क्योंकि धागा DLLs कोड है कि अनलोड में अब भी है ...

अब मैं एक नुकसान में हूँ यकीन है कि dll केवल उतार दिया जाता है जब बनाने के लिए कैसे बाकी सब कुछ हटा दिए जाने के बाद स्पष्ट रूप से डीएल को मुक्त करने के अलावा वापस जाने के अलावा कोई शेष वस्तुएं नहीं हैं;

int main() 
{ 
    ExampleDll *dll = LoadDll("bin\\example.dll"); 
    restOfProgram(); 
    delete dll; 
} 

यह दृष्टिकोण मुश्किल हो जाता है जब DLLs यदि उपयोगकर्ता D3D से बदले गए विकल्प में ओपन करने के लिए saftly लोड करने के लिए/उतार मध्य कार्यक्रम, यानी की जरूरत है।

उत्तर

6

मान लीजिए कि आप लाइब्रेरी को अनलोड करते समय थ्रेड को समाप्त नहीं करना चाहते हैं (अन्यथा, MSalters देखें), आपको लाइब्रेरी को कॉलर से मुक्त करने की आवश्यकता है।

COM हल करता है कि एक इन-डीएलएल इंस्टेंस काउंटर (आपके जैसे, अगर मैं आपको सही ढंग से समझता हूं) द्वारा, और वैश्विक निर्यात किए गए CanUnloadNow फ़ंक्शन को कॉल करके विनियमन की जांच कर रहा है।

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

इसके अलावा, यदि आप परिपत्र डीएलएल निर्भरता (घटक DllA.X संदर्भ DllB.Y, जो DllA.Z संदर्भित करता है) प्राप्त करते हैं, तो इनमें से कोई भी योजना अधिक सहायता नहीं करती है। मैंने अभी तक इसका अच्छा समाधान नहीं किया है जो वैश्विक ज्ञान को पुनः प्राप्त नहीं करता है।

+0

ठीक है, मुझे एक विचार था, क्या होगा अगर डीएलएस रिलीज() विधि ने एक बूल लौटाया, झूठा अगर कोई शेष रिफ्रेंस नहीं था, तो एक विशेष DllPtr मुफ्त लाइब्रेरी को कॉल कर सकता है अगर रिलीज झूठी –

+0

लौटा दी लेकिन अभी भी आखिरी की समस्या है यदि डीएलपीआरआर पहले हटा दिए जाते हैं तो डीएलएल में रिफ्रेंस हटा दिया जा रहा है ... मैं COM दृष्टिकोण को लागू करने के बारे में कैसे जाउंगा ताकि मैं ढेर और स्थैतिक (यानी ग्लोबल्स) नष्ट होने के बाद डीएलएल को जारी रख सकूं क्योंकि केवल तभी यह स्वयं को गर्वित किया जाता है कोई रेफरी नहीं? –

+0

आपको एक प्रकार की "क्लीनर" ऑब्जेक्ट की आवश्यकता होगी जो डीएल में नहीं है जिसे आप सफलतापूर्वक इस तरह के डीएलएल को अनलोड करने के लिए अनलोड कर रहे हैं, यह लगभग ole32.dll करता है जब CoUnitialize कहा जाता है। – Ismael

0

MSDN इस विषय पर स्पष्ट है:।। "एक धागा है कि DLL जिसमें यह निष्पादित हो रहा है उतारना चाहिए और उसके बाद ही समाप्त बजाय FreeLibrary और ExitThread बुला अलग अन्यथा, एक रेस स्थिति में हो सकता है की FreeLibraryAndExitThread बुलाना चाहिए जानकारी के लिए, FreeLibraryAndExitThread की टिप्पणियां अनुभाग देखें

+0

मैं थ्रेड को समाप्त नहीं करना चाहता हूं, बस डीएल को मुक्त करें और exe/पिछले dll –

+0

पर वापस लौटें, यह समझ में नहीं आता है - आपने बस सभी रिटर्न स्टेटमेंट को भी उतार दिया है! – MSalters

1

मामले के लिए जहां DLL रन टाइम पर स्विच किया गया है, मैं DLL द्वारा बनाई गई वस्तुओं के लिए स्मार्ट सूचक प्रणाली से बचने चाहते हैं और इस तरह की एक प्रणाली का उपयोग करें:।

    |-----------------------| |--------------------------| 
        | Abstraction Interface | | Implementation Interface | 
        |-----------------------| |--------------------------| 
          ^      ^
           |       | 
|-------------|1  *|-------------------|*  *|----------------| 
| Application |-------| Abstraction Layer |--------| Implementation | 
|-------------|  |-------------------|  |----------------| 

\------------- Main Program ------------------/ \-------- DLL --------/ 

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

0

ठीक है मुझे लगता है कि सबसे अच्छा विकल्प डीएल को मतदान करने के COM दृष्टिकोण का उपयोग करना है ताकि यह देखने के लिए कि इसे अनलोड किया जा सकता है या नहीं। मैं ऐसा करने के बारे में कैसे जा सकता हूं, हालांकि मैं बाकी सब कुछ बंद होने के बाद डीएल को मतदान जारी रख सकता हूं (यानी मुख्य धागा समाप्त हो गया है)? क्या मुझे ऐसा करने के लिए पूरी तरह से पृथक प्रक्रिया बनाने की ज़रूरत है, इस मामले में मैं इसे कैसे कर सकता हूं ताकि यह अलग प्रक्रिया सभी लोड किए गए डीएलएस के बारे में जान सके, और इस तरह से जिसने प्रोफेसर पर बहुत कम प्रभाव डाला है?

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

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