2014-05-06 16 views
8

के साथ एक अप्रबंधित डीएल से निपटने के लिए मेरे पास एक सी # एप्लिकेशन है जो कुछ हार्डवेयर तक पहुंचने के लिए किसी तृतीय-पक्ष अप्रबंधित असेंबली पर निर्भर करता है।मेमोरी लीक

अप्रबंधित कोड में एक स्मृति रिसाव है जो प्रत्येक पहुंच के बाद ~ 10 एमबी द्वारा स्मृति खपत में वृद्धि करेगा। समस्या ज्ञात है; कोई बगफिक्स उपलब्ध नहीं है।

क्या कोई तरीका है कि मैं नियमित रूप से पुनरारंभ किए बिना इस असेंबली का उपयोग जारी रख सकता हूं?

मैंने एक अलग ऐपडोमेन बनाने की कोशिश की, उस ऐपडोमेन में अपमानजनक कोड appDomain.CreateInstanceAndUnwrap() के माध्यम से लोड करें और बाद में AppDomain.Unload() के माध्यम से डोमेन को उतार दिया। हालांकि यह स्पष्ट रूप से उस डोमेन द्वारा उपयोग की गई अप्रबंधित स्मृति को मुक्त नहीं करता है, केवल प्रबंधित स्मृति।

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

क्या इस रिसाव असेंबली को कम करने का एक और तरीका है और इसे फिर से शुरू किए बिना अपनी याददाश्त जारी करने के लिए मजबूर करें।

+3

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

+0

@ LasseV.Karlsen - एक उत्तर के रूप में conisder कॉपी पेस्ट। मुझे यहां कुछ और नहीं कहना है। –

+0

मुझे लगता है कि एप्लिकेशन को विभाजित करने के लिए आपकी सबसे अच्छी शर्त है। बड़ी मात्रा में डेटा को स्थानांतरित करने के लिए साझा स्मृति का उपयोग करके आप कुछ मंदी से बच सकते हैं। लाइब्रेरी के लिए 'malloc'/'free' (या' new' /' delete') को हुक करना और DLL के लिए अपना स्वयं का अलग ढेर लागू करना एक विकल्प होगा। इस पर निर्भर करता है कि क्या डीएलएल गतिशील सी/सी ++ रनटाइम या स्थैतिक एक का उपयोग करता है, यह बेहद जटिल से निराशाजनक रूप से जटिल हो जाएगा। –

उत्तर

4

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

आप विकल्पों में से एक जोड़े को मिल गया है, लेकिन मुझे नहीं लगता कि उनमें से किसी को अपील कर रहे हैं:

  1. आप अपने मुख्य आवेदन में dll का उपयोग कर रख सकते हैं। आप अपने उपयोगकर्ताओं/ग्राहकों को सलाह दे सकते हैं कि उन्हें बहुत सारी मेमोरी उपलब्ध होनी चाहिए, लेकिन समय-समय पर एप्लिकेशन को पुनरारंभ करना होगा। कार्यक्रम वास्तव में क्रैश होने से पहले आप स्मृति की स्थिति का पता लगाना चाहते हैं, उपयोगकर्ता को इसे फिर से शुरू करने के लिए धीरे-धीरे प्रोडक्ट करना चाहते हैं, बजाय अपवाद के साथ कड़ी मेहनत करने के बजाय।
  2. आप डीएलएल की डेटा संरचनाओं में खोदने का प्रयास कर सकते हैं। यदि डीएल वास्तव में बदल रहा है (यानी नए संस्करण आ रहे हैं), तो मैं दृढ़ता से सुझाव देता हूं कि आप मेमोरी रिसाव को ठीक करने के लिए लेखक पर कड़ी मेहनत करें। हालांकि, यह असंभव लगता है क्योंकि मुझे यकीन है कि रिसाव होगा यदि कोई नया संस्करण निकला हो। इस प्रकार, उस कोड के निचले हिस्से में सीधे अपना कोड डालना समाधान हो सकता है। अप्रत्याशित स्मृति का संदर्भ देने वाले वास्तविक पॉइंटर तक पहुंचने से आप फिट होने पर मैन्युअल रूप से इसे मुक्त कर सकते हैं।
  3. आप समस्या को अलग प्रक्रिया में अलग कर सकते हैं। उस पर और अधिक।
  4. आप डीएलएल की कार्यक्षमता को फिर से कार्यान्वित कर सकते हैं।

यहां 5 वां या 6 वां विकल्प हो सकता है, लेकिन लगता है कि उपरोक्त 4 में मेरे सिर के ऊपर से आने वाली चीज़ों को शामिल किया गया है। और सबसे तेजी से इंट्रा-प्रक्रिया संचार चैनल आप पा सकते हैं का उपयोग करके उसमें पंप अनुरोध

मैं एक प्रक्रिया में तेजी स्पिन जाएगा,:

एक अलग प्रक्रिया में अलग बारे में, यहाँ मैं पहली बार करने की कोशिश करेंगे क्या। पाइप्स एक अच्छी फिट, या स्मृति-मैप की गई फाइलें प्रतीत होती हैं।

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

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

यह अस्थायी रूप से संक्रमण के दौरान जीवित अतिरिक्त प्रक्रिया होने के खर्च पर डाउनटाइम को कम करेगा।

यह सब आपके वास्तविक परिदृश्यों पर निर्भर करता है। यदि आपको इस डीएल 100 या कई बार बार-बार कॉल करने की आवश्यकता है, तो किसी भी मामले में इंट्रा-प्रोसेस संचार करना संभव नहीं है।

1

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

मेमोरी लीक से छुटकारा पाने के लिए आपको मुक्त स्मृति मुक्त करनी है और इसे करने के दो तरीके हैं - प्रक्रिया को समाप्त करें और ऑपरेटिंग सिस्टम को ऐसा करने दें या इसे स्वयं मुक्त करें। इसे स्वयं मुक्त करने के लिए आपको डीएलएल के सार्वजनिक इंटरफ़ेस के माध्यम से या प्रक्रिया के ढेर का निरीक्षण करके, इसे डीएलएल के सार्वजनिक इंटरफ़ेस के माध्यम से प्राप्त करने के द्वारा मेमोरी को हैंडल पकड़ना होगा। यह शायद करने योग्य है लेकिन मुझे लगता है कि यह न तो मजेदार होगा, न ही आसान और शायद मजबूत भी नहीं।

तुलना में दो प्रक्रियाओं के साथ समाधान और नियमित रूप से लीकिंग को फिर से शुरू करने में आसान और मजबूत लगता है। मैं प्रदर्शन के बारे में चिंतित नहीं होगा क्योंकि उदाहरण के लिए आप अपना डेटा साझा करने और इसे कॉपी करने से बचने के लिए memory mapped files का उपयोग कर सकते हैं।

सबसे आसान समाधान निश्चित रूप से स्मृति रिसाव को ठीक कर रहा है या शायद डीएलएल को उपलब्ध कराने या पैच करने पर स्रोत को ठीक करके स्वयं को ठीक कर रहा है।

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