c++ मेमोरी लीक कभी ठीक है?




memory-leaks (24)

क्या आपके सी या सी ++ एप्लिकेशन में मेमोरी लीक होने के लिए कभी स्वीकार्य है?

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

क्या होगा अगर किसी तीसरे पक्ष की लाइब्रेरी ने आपको इस स्थिति को मजबूर कर दिया? उस तीसरे पक्ष की लाइब्रेरी का उपयोग करने से इंकार कर देगा इससे कोई फर्क नहीं पड़ता कि यह अन्यथा कितना अच्छा हो सकता है?

मुझे केवल एक व्यावहारिक नुकसान दिखाई देता है, और यह है कि ये सौम्य रिसाव स्मृति रिसाव पहचान उपकरण के साथ झूठी सकारात्मक के रूप में दिखाई देंगे।


मुझे लगता है कि यह ठीक है अगर आप स्मृति को रिसाव करने के लिए एक प्रोग्राम लिख रहे हैं (यानी सिस्टम प्रदर्शन पर मेमोरी लीक के प्रभाव का परीक्षण करने के लिए)।


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

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

लेकिन मूल रूप से यदि स्मृति रिसाव एक ज्ञात मात्रा 512 केबी बफर या कुछ है तो यह एक गैर मुद्दा है। यदि मेमोरी रिसाव हर बार जब आप लाइब्रेरी कॉल करते हैं, तो आपकी याददाश्त 512 केबी तक बढ़ जाती है और मुक्त नहीं होती है, तो आपको कोई समस्या हो सकती है। यदि आप इसे दस्तावेज करते हैं और कॉल को निष्पादित करने की संख्या को नियंत्रित करते हैं तो यह प्रबंधनीय हो सकता है। लेकिन फिर आपको वास्तव में दस्तावेज़ीकरण की आवश्यकता है क्योंकि 512 अधिक नहीं है, जबकि 512 से अधिक कॉल एक लाख है।

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


मैं वास्तव में एक स्मृति रिसाव क्या है की इतनी गलत परिभाषाओं को देखकर हैरान हूं। एक ठोस परिभाषा के बिना, यह एक बुरी बात है या नहीं, इस पर एक चर्चा कहीं भी नहीं जाएगी।

जैसा कि कुछ टिप्पणीकारों ने सही ढंग से इंगित किया है, एक स्मृति रिसाव केवल तब होता है जब किसी प्रक्रिया द्वारा आवंटित स्मृति इस सीमा तक समाप्त हो जाती है कि प्रक्रिया अब संदर्भित करने या हटाने में सक्षम नहीं है।

एक प्रक्रिया जो अधिक से अधिक स्मृति को पकड़ रही है वह जरूरी नहीं है। जब तक वह उस स्मृति को संदर्भित और अस्वीकार करने में सक्षम है, तब यह प्रक्रिया के स्पष्ट नियंत्रण में रहता है और लीक नहीं हुआ है। प्रक्रिया को बुरी तरह से डिजाइन किया जा सकता है, खासकर उस प्रणाली के संदर्भ में जहां स्मृति सीमित है, लेकिन यह रिसाव के समान नहीं है। Conversely, losing scope of, say, a 32 byte buffer is still a leak, even though the amount of memory leaked is small. If you think this is insignificant, wait until someone wraps an algorithm around your library call and calls it 10,000 times.

I see no reason whatsoever to allow leaks in your own code, however small. Modern programming languages such as C and C++ go to great lengths to help programmers prevent such leaks and there is rarely a good argument not to adopt good programming techniques - especially when coupled with specific language facilities - to prevent leaks.

As regards existing or third party code, where your control over quality or ability to make a change may be highly limited, depending on the severity of the leak, you may be forced to accept or take mitigating action such as restarting your process regularly to reduce the effect of the leak.

It may not be possible to change or replace the existing (leaking) code, and therefore you may be bound to accept it. However, this is not the same as declaring that it's OK.


मुझे यकीन है कि कोई हां कहने के कारण से आ सकता है, लेकिन यह मैं नहीं होगा। नहीं कहने के बजाय, मैं यह कहने जा रहा हूं कि यह एक हां / नहीं सवाल होना चाहिए। मेमोरी लीक को प्रबंधित करने या रखने के तरीके हैं, और कई प्रणालियों में उन्हें हैं।

ऐसे उपकरणों पर नासा सिस्टम हैं जो पृथ्वी को छोड़ देते हैं जो इसके लिए योजना बनाते हैं। सिस्टम स्वचालित रूप से हर बार स्वचालित रूप से रीबूट हो जाएंगे ताकि स्मृति रिसाव पूरे ऑपरेशन के लिए घातक न हो जाए। बस रोकथाम का एक उदाहरण।


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

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

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


सिद्धांत रूप में, अभ्यास में यह निर्भर करता है

यह वास्तव में इस बात पर निर्भर करता है कि कार्यक्रम कितना डेटा काम कर रहा है, प्रोग्राम कितनी बार चलता है और चाहे वह लगातार चल रहा हो या नहीं।

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

दूसरी तरफ यदि मेरे पास ऐसा प्रोग्राम है जो लाखों रिकॉर्ड रिकॉर्ड करता है और लंबे समय तक चलता है, तो एक छोटी मेमोरी रिसाव मशीन को पर्याप्त समय दे सकती है।

तीसरे पक्ष के पुस्तकालयों के लिए जिनके पास रिसाव है, यदि वे कोई समस्या पैदा करते हैं तो पुस्तकालय को ठीक करें या बेहतर विकल्प ढूंढें। अगर इससे कोई समस्या नहीं आती है, तो क्या इससे वाकई कोई फर्क पड़ता है?


I'll answer no.

In theory, the operating system will clean up after you if you leave a mess (now that's just rude, but since computers don't have feelings it might be acceptable). But you can't anticipate every possible situation that might occur when your program is run. Therefore (unless you are able to conduct a formal proof of some behaviour), creating memory leaks is just irresponsible and sloppy from a professional point of view.

If a third-party component leaks memory, this is a very strong argument against using it, not only because of the imminent effect but also because it shows that the programmers work sloppily and that this might also impact other metrics. Now, when considering legacy systems this is difficult (consider web browsing components: to my knowledge, they all leak memory) but it should be the norm.


आइए पहले हमारी परिभाषाओं को सही बनाएं। एक स्मृति रिसाव तब होती है जब स्मृति गतिशील रूप से आवंटित की जाती है, उदाहरण के लिए malloc() , और स्मृति के सभी संदर्भ इसी प्रकार के बिना खो जाते हैं। एक बनाने का एक आसान तरीका इस तरह है:

#define BLK ((size_t)1024)
while(1){
    void * vp = malloc(BLK);
}

ध्यान दें कि हर बार (1) लूप के आसपास, 1024 (+ ओवरहेड) बाइट आवंटित किए जाते हैं, और नया पता vp को सौंपा गया है; पिछले malloc'ed ब्लॉक के लिए कोई शेष सूचक नहीं है। इस कार्यक्रम को तब तक चलाने की गारंटी दी जाती है जब तक ढेर खत्म नहीं हो जाता है, और किसी भी मॉलोकेड मेमोरी को पुनर्प्राप्त करने का कोई तरीका नहीं है। मेमोरी ढेर से "लीकिंग" है, फिर कभी नहीं देखा जा सकता है।

आप क्या वर्णन कर रहे हैं, हालांकि, ध्वनि की तरह

int main(){
    void * vp = malloc(LOTS);
    // Go do something useful
    return 0;
}

आप स्मृति आवंटित करते हैं, प्रोग्राम समाप्त होने तक इसके साथ काम करते हैं। यह एक स्मृति रिसाव नहीं है; यह प्रोग्राम को खराब नहीं करता है, और जब प्रोग्राम समाप्त हो जाता है तो सभी मेमोरी स्वचालित रूप से खराब हो जाएंगी।

आम तौर पर, आपको स्मृति रिसाव से बचना चाहिए। सबसे पहले, क्योंकि आप से ऊपर की ऊंचाई और हैंगर पर वापस ईंधन, स्मृति जो लीक हो गई है और उसे पुनर्प्राप्त नहीं किया जा सकता है; दूसरा, शुरुआत में मेमोरी लीक को खोजने के बाद शुरुआत में, कोड को सही ढंग से कोड करना बहुत आसान है।


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

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

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

आखिरकार, मैंने फैसला किया कि एक ऐप के लिए 150 बाइट्स लेना जो रैम के एक छिद्र के आसपास इस्तेमाल होता है और एक समर्पित मशीन पर दौड़ता है, उसे ठीक करने के लायक नहीं था, इसलिए मैंने एक टिप्पणी लिखी कि यह लीक हो गया है, ठीक करने के लिए क्या बदला जाना चाहिए यह, और उस समय यह क्यों लायक नहीं था।


Its really not a leak if its intentional and its not a problem unless its a significant amount of memory, or could grow to be a significant amount of memory. Its fairly common to not cleanup global allocations during the lifetime of a program. If the leak is in a server or long running app, grows over time, then its a problem.


I see the same problem as all scenario questions like this: What happens when the program changes, and suddenly that little memory leak is being called ten million times and the end of your program is in a different place so it does matter? If it's in a library then log a bug with the library maintainers, don't put a leak into your own code.


मेरा मानना ​​है कि जवाब नहीं है, कभी भी स्मृति रिसाव की अनुमति न दें, और मेरे पास कुछ कारण हैं जिन्हें मैंने स्पष्ट रूप से नहीं देखा है। यहां बहुत अच्छे तकनीकी उत्तर हैं लेकिन मुझे लगता है कि वास्तविक उत्तर अधिक सामाजिक / मानव कारणों पर निर्भर करता है।

(सबसे पहले, ध्यान दें कि जैसा कि दूसरों ने उल्लेख किया है, एक वास्तविक रिसाव तब होता है जब आपका प्रोग्राम, किसी भी समय, स्मृति संसाधनों का ट्रैक खो देता है, जिसे आवंटित किया गया है। सी में, ऐसा तब होता है जब आप किसी पॉइंटर पर malloc() करते हैं और उस पॉइंटर को गुंजाइश छोड़ देते हैं एक free() पहले बिना।)

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

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

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

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

एक और सामाजिक पहलू भी है। malloc() और free() उचित उपयोग से, जो भी आपका कोड देखता है वह आसानी से होगा; आप अपने संसाधनों का प्रबंधन कर रहे हैं। यदि आप नहीं करते हैं, तो वे तुरंत एक समस्या पर संदेह करेंगे।

हो सकता है कि आपने यह काम किया है कि स्मृति रिसाव इस संदर्भ में कुछ भी नुकसान नहीं पहुंचाता है, लेकिन कोड के उस टुकड़े को पढ़ते समय आपके कोड के प्रत्येक रखरखाव को उसके सिर में भी काम करना होगा। free() का उपयोग करके आप इस मुद्दे पर विचार करने की आवश्यकता को हटा देते हैं।

अंत में, प्रोग्रामिंग एक संवेदी भाषा के लिए एक प्रक्रिया का एक मानसिक मॉडल लिख रही है ताकि एक व्यक्ति और कंप्यूटर पूरी तरह से प्रक्रिया को समझ सके। अच्छे प्रोग्रामिंग अभ्यास का एक महत्वपूर्ण हिस्सा कभी अनावश्यक अस्पष्टता पेश नहीं कर रहा है।

स्मार्ट प्रोग्रामिंग लचीला और सामान्य है। खराब प्रोग्रामिंग संदिग्ध है।


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


यह इतना डोमेन-विशिष्ट है कि इसका उत्तर देने योग्य नहीं है। अपने सनकी सिर का प्रयोग करें।

  • अंतरिक्ष शटल ऑपरेटिंग सिस्टम: नहीं, कोई मेमोरी लीक की अनुमति नहीं है
  • तेजी से विकास प्रमाण-अवधारणा कोड: उन सभी स्मृति रिसाव को ठीक करना समय की बर्बादी है।

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

सभी को ठीक करने के लिए उत्पाद रिलीज में देरी की अवसर लागत ($$$) लेकिन सबसे खराब मेमोरी लीक आमतौर पर "मैला या गैर-व्यावसायिक" होने की भावनाओं को बौद्ध करती है। आपका मालिक आपको पैसे कमाने के लिए भुगतान करता है, न कि गर्म, अस्पष्ट भावनाएं प्राप्त करने के लिए।


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

इसके साथ ही, ऐसे समय भी होंगे जब आपके पास वास्तविक मेमोरी लीक होंगी जिन्हें खोजने में बहुत मुश्किल होती है या उन्हें ठीक करना मुश्किल होता है। तो अब प्रश्न बन गया है कि उन्हें कोड में छोड़ना ठीक है?

आदर्श जवाब है, "नहीं, कभी नहीं।" एक और व्यावहारिक उत्तर "नहीं, लगभग कभी नहीं" हो सकता है। अक्सर वास्तविक जीवन में आपके पास कार्यों की संकल्प और अंतहीन सूची के लिए संसाधनों और समय की सीमित संख्या होती है। जब एक कार्य मेमोरी लीक को खत्म कर रहा है, तो कम रिटर्न का कानून अक्सर खेलने के लिए आता है। आप एक हफ्ते में एक आवेदन में सभी मेमोरी लीक का 98% कह सकते हैं, लेकिन शेष 2% महीने लग सकते हैं। कुछ मामलों में कोड के एक बड़े रिफैक्टरिंग के बिना एप्लिकेशन के आर्किटेक्चर की वजह से कुछ लीक को खत्म करना भी असंभव हो सकता है। आपको शेष 2% को समाप्त करने की लागत और लाभों का वजन करना होगा।


नहीं।

पेशेवरों के रूप में, सवाल यह है कि हमें खुद से नहीं पूछना चाहिए, "क्या यह कभी करना ठीक है?" बल्कि "क्या ऐसा करने का कोई अच्छा कारण है?" और "उस स्मृति रिसाव को शिकार करना एक दर्द है" एक अच्छा कारण नहीं है।

मैं चीजों को सरल रखना पसंद करता हूं। और सरल नियम यह है कि मेरे कार्यक्रम में कोई स्मृति रिसाव नहीं होना चाहिए।

इससे मेरा जीवन भी सरल हो जाता है। अगर मैं मेमोरी रिसाव का पता लगाता हूं, तो यह निर्धारित करने के लिए कि क्या यह एक "स्वीकार्य" स्मृति रिसाव है, मैं कुछ विस्तृत निर्णय वृक्ष संरचना के माध्यम से इसे चलाने के बजाय इसे खत्म कर देता हूं।

यह संकलक चेतावनियों के समान है - क्या चेतावनी मेरे विशेष आवेदन के लिए घातक होगी? शायद नहीं।

लेकिन यह अंततः पेशेवर अनुशासन का मामला है। टोलरेटिंग कंपाइलर चेतावनियां और मेमोरी लीक को सहन करना एक बुरी आदत है जो आखिरकार मुझे पीछे की ओर काट देगी।

चीजों को चरम पर ले जाने के लिए, क्या कभी एक सर्जन के लिए एक रोगी के अंदर ऑपरेटिंग उपकरण का कुछ टुकड़ा छोड़ना स्वीकार्य होगा?

यद्यपि यह संभव है कि एक परिस्थिति उत्पन्न हो सकती है जहां उपकरण के उस टुकड़े को हटाने की लागत / जोखिम इसे छोड़ने की लागत / जोखिम से अधिक है, और ऐसी परिस्थितियां हो सकती हैं जहां यह हानिकारक हो, अगर मैंने यह प्रश्न SurgeonOverflow.com पर पोस्ट किया और "नहीं" के अलावा कोई जवाब देखा, यह चिकित्सा पेशे में अपने आत्मविश्वास को गंभीरता से कमजोर कर देगा।

-

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


आवेदन चलाने के बाद ओएस साफ होने के साथ अवधारणात्मक रूप से कुछ भी गलत नहीं है।

यह वास्तव में आवेदन पर निर्भर करता है और यह कैसे चलाया जाएगा। सप्ताह में चलाने के लिए आवश्यक एप्लिकेशन में लगातार होने वाली लीक की देखभाल की जानी चाहिए, लेकिन एक छोटा सा टूल जो बिना किसी स्मृति की आवश्यकता के परिणाम की गणना करता है, एक समस्या नहीं होनी चाहिए।

एक कारण है कि कई स्क्रिप्टिंग भाषा कचरा नहीं है चक्रीय संदर्भों को इकट्ठा करते हैं ... उनके उपयोग पैटर्न के लिए, यह एक वास्तविक समस्या नहीं है और इस तरह बर्बाद स्मृति के रूप में संसाधनों की बर्बादी होगी।


I think you've answered your own question. The biggest drawback is how they interfere with the memory leak detection tools, but I think that drawback is a HUGE drawback for certain types of applications.

I work with legacy server applications that are supposed to be rock solid but they have leaks and the globals DO get in the way of the memory detection tools. It's a big deal.

In the book "Collapse" by Jared Diamond, the author wonders about what the guy was thinking who cut down the last tree on Easter Island, the tree he would have needed in order to build a canoe to get off the island. I wonder about the day many years ago when that first global was added to our codebase. THAT was the day it should have been caught.


यहां तक ​​कि यदि आप सुनिश्चित हैं कि आपकी 'ज्ञात' मेमोरी रिसाव खतरे का कारण नहीं बनती है, तो ऐसा न करें। सबसे अच्छा, यह आपके लिए एक अलग समय और स्थान पर एक समान और शायद अधिक महत्वपूर्ण गलती करने का एक तरीका देगा।

मेरे लिए, यह पूछना प्रश्न पूछने जैसा है "क्या मैं सुबह 3 बजे लाल बत्ती तोड़ सकता हूं जब कोई भी आसपास नहीं है?"। निश्चित रूप से, यह उस समय किसी भी परेशानी का कारण नहीं बन सकता है, लेकिन यह आपके लिए घंटों में ऐसा करने के लिए एक लीवर प्रदान करेगा!


This was already discussed ad nauseam . Bottom line is that a memory leak is a bug and must be fixed. If a third party library leaks memory, it makes one wonder what else is wrong with it, no? If you were building a car, would you use an engine that is occasionally leaking oil? After all, somebody else made the engine, so it's not your fault and you can't fix it, right?


मैं एक हाथ पर "सौम्य" लीक की संख्या पर भरोसा कर सकता हूं जिसे मैंने समय के साथ देखा है।

तो जवाब एक बहुत योग्य हां है।

एक उदाहरण। यदि आपके पास एक सिंगलटन संसाधन है जिसके लिए एक गोलाकार कतार या डेक स्टोर करने के लिए बफर की आवश्यकता है लेकिन यह नहीं पता कि बफर को कितना बड़ा होना चाहिए और लॉकिंग या प्रत्येक पाठक के ऊपरी हिस्से को बर्दाश्त नहीं कर सकता है, फिर एक तेजी से दोगुना बफर आवंटित करना है, लेकिन पुराने लोगों को मुक्त नहीं करना प्रति कतार / डेक की स्मृति की एक सीमित मात्रा को रिसाव करेगा। इनके लिए लाभ यह है कि वे नाटकीय रूप से हर पहुंच को तेज़ी से बढ़ाते हैं और लॉक के लिए विवाद को खतरे में डालकर मल्टीप्रोसेसर समाधानों के एसिम्प्टोटिक्स को बदल सकते हैं।

मैंने इस दृष्टिकोण को प्रति-सीपीयू वर्क-स्टीलिंग डेक जैसे बहुत स्पष्ट रूप से निश्चित गणना वाले चीजों के लिए बहुत लाभ के लिए उपयोग किया है, और हंस में सिंगलटन /proc/self/maps राज्य को पकड़ने के लिए उपयोग किए जाने वाले बफर में बहुत कम डिग्री के लिए सी / सी ++ के लिए बोहेम के रूढ़िवादी कचरा कलेक्टर, जिसका उपयोग रूट सेट आदि का पता लगाने के लिए किया जाता है।

तकनीकी रूप से एक रिसाव के दौरान, इन दोनों मामलों में आकार में बंधे हैं और बढ़ते परिपत्र कार्य में डेक मामले चोरी करना कतारों के लिए स्मृति उपयोग में 2 वृद्धि के बाध्य कारक के बदले में एक बड़ी प्रदर्शन जीत है।


जबकि अधिकांश उत्तर वास्तविक स्मृति रिसाव पर ध्यान केंद्रित करते हैं (जो कि ठीक नहीं हैं, क्योंकि वे मैला कोडिंग का संकेत हैं), प्रश्न का यह हिस्सा मेरे लिए और अधिक दिलचस्प प्रतीत होता है:

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

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

तो, मूल मामले पर, यह आईएमएचओ पूरी तरह से ठीक है, इतना है कि सबसे शक्तिशाली रिसाव डिटेक्टरों में से एक वालग्रिंड, अनुरोध किए जाने पर ही ऐसे लीक का इलाज करेगा। वालग्रिंड पर, जब आप इसे पहले बिना मुक्त किए पॉइंटर को ओवरराइट करते हैं, तो इसे स्मृति रिसाव के रूप में माना जाता है, क्योंकि यह फिर से होने की संभावना है और ढेर को अंतहीन रूप से विकसित करने की संभावना है।

फिर, nfreed मेमोरी ब्लॉक नहीं हैं जो अभी भी पहुंच योग्य हैं। कोई भी उन सभी को बाहर निकलने पर मुक्त कर सकता है, लेकिन यह सिर्फ समय में बर्बाद है। मुद्दा यह है कि अगर उन्हें पहले मुक्त किया जा सकता है। किसी भी मामले में स्मृति खपत को कम करना उपयोगी है।


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

यह सच नहीं है। ऑपरेटिंग सिस्टम आमतौर पर 4KiB पृष्ठों में स्मृति का प्रबंधन करते हैं। malloc और मेमोरी मैनेजमेंट के अन्य प्रकार ओएस से पेज प्राप्त करते हैं और फिट होने पर उन्हें उप-प्रबंधित करते हैं। यह काफी संभावना है कि free() पृष्ठ को ऑपरेटिंग सिस्टम पर वापस नहीं करेगा, इस धारणा के तहत कि आपका प्रोग्राम बाद में और अधिक स्मृति को मॉल करेगा।

मैं यह नहीं कह रहा हूं कि free() ऑपरेटिंग सिस्टम को कभी याद नहीं करता है। ऐसा हो सकता है, खासकर यदि आप स्मृति के बड़े हिस्सों को मुक्त कर रहे हैं। लेकिन कोई गारंटी नहीं है।

महत्वपूर्ण तथ्य: यदि आप उस स्मृति को मुक्त नहीं करते हैं जिसकी आपको अब आवश्यकता नहीं है, तो आगे के मॉलॉक्स को और भी स्मृति का उपभोग करने की गारंटी है। लेकिन यदि आप पहले मुक्त करते हैं, तो मॉलोक इसके बजाय मुक्त स्मृति का पुनः उपयोग कर सकता है।

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

समाप्ति से पहले स्मृति मुक्त करने के बारे में अधिक जानकारी के लिए यह टिप्पणी भी देखें।

एक टिप्पणीकर्ता यह समझ में नहीं आया कि free() कॉलिंग free() स्वचालित रूप से अन्य प्रोग्रामों को मुक्त स्मृति का उपयोग करने की अनुमति नहीं देती है। लेकिन यह इस जवाब का पूरा बिंदु है!

इसलिए, लोगों को मनाने के लिए, मैं एक उदाहरण प्रदर्शित करूंगा जहां मुफ्त () बहुत कम अच्छा करता है। गणित को पालन करने में आसान बनाने के लिए, मैं दिखाऊंगा कि ओएस 4000 बाइट पृष्ठों में स्मृति का प्रबंधन करता है।

मान लीजिए कि आप दस हजार 100-बाइट ब्लॉक आवंटित करते हैं (सादगी के लिए मैं अतिरिक्त आवंटन को अनदेखा कर दूंगा जो इन आवंटन को प्रबंधित करने के लिए आवश्यक होंगे)। यह 1 एमबी, या 250 पृष्ठों का उपभोग करता है। यदि आप यादृच्छिक रूप से इन ब्लॉकों में से 9000 मुक्त करते हैं, तो आपको केवल 1000 ब्लॉक के साथ छोड़ दिया जाता है - लेकिन वे सभी जगह बिखरे हुए हैं। सांख्यिकीय रूप से, लगभग 5 पृष्ठ खाली होंगे। अन्य 245 में प्रत्येक में कम से कम एक आवंटित ब्लॉक होगा। यह 980 केबी मेमोरी की मात्रा है, जिसे संभवतः ऑपरेटिंग सिस्टम द्वारा पुनः प्राप्त नहीं किया जा सकता है - भले ही आपके पास अब केवल 100 केबी आवंटित हो!

दूसरी तरफ, अब आप अपने प्रोग्राम को गड़बड़ कर रहे स्मृति की मात्रा को बढ़ाए बिना 9 00 अधिक ब्लॉकों को malloc () कर सकते हैं।

यहां तक ​​कि जब free() तकनीकी रूप से ओएस को स्मृति लौटा सकता है, तो ऐसा नहीं हो सकता है। free() को जल्दी से ऑपरेटिंग और स्मृति को बचाने के बीच संतुलन प्राप्त करने की आवश्यकता है। और इसके अलावा, एक कार्यक्रम जो पहले से ही बहुत सारी स्मृति आवंटित कर चुका है और फिर इसे मुक्त कर दिया गया है, फिर भी ऐसा करने की संभावना है। अनुरोध के बाद अनुरोध के बाद एक वेब सर्वर को अनुरोध संभाल करने की आवश्यकता होती है - कुछ "स्लेक" मेमोरी उपलब्ध रखने के लिए यह समझ में आता है ताकि आपको हर समय स्मृति के लिए ओएस से पूछने की आवश्यकता न हो।


I agree with vfilby – it depends. In Windows, we treat memory leaks as relatively serous bugs. But, it very much depends on the component.

For example, memory leaks are not very serious for components that run rarely, and for limited periods of time. These components run, do theire work, then exit. When they exit all their memory is freed implicitly.

However, memory leaks in services or other long run components (like the shell) are very serious. The reason is that these bugs 'steal' memory over time. The only way to recover this is to restart the components. Most people don't know how to restart a service or the shell – so if their system performance suffers, they just reboot.

So, if you have a leak – evaluate its impact two ways

  1. To your software and your user's experience.
  2. To the system (and the user) in terms of being frugal with system resources.
  3. Impact of the fix on maintenance and reliability.
  4. Likelihood of causing a regression somewhere else.

Foredecker





memory-leaks