2009-08-05 12 views
29

हटाएं हम मॉलोक और सी ++ में नए का उपयोग करके सी में स्मृति आवंटित करते हैं। मुझे पता है कि आवंटित स्मृति को मुक्त किया जा सकता है या सी में मुफ्त में ओएस को वापस दिया जा सकता है और सी ++ में हटा दिया जा सकता है। अगर मैं स्मृति आवंटित करने के बाद मुक्त/हटाएं का उपयोग करना भूल गया, तो इसका मतलब है कि स्मृति रिसाव होगी।सी, सी ++ में मेमोरी लीक; मुक्त करने के लिए भूल गए,

अब, मेरा सवाल यह है कि, यह स्मृति केवल कार्यक्रम के निष्पादन की अवधि के दौरान रिसाव है; या यह स्थायी रिसाव/हानि है या सिस्टम को पुनरारंभ करने के बाद इसे फिर से प्राप्त किया जाता है? वास्तव में आंतरिक प्रक्रिया क्या है? स्मृति रिसाव/हानि वास्तव में क्या मतलब है?

यदि कोई इसे विस्तार से समझा सकता है या मुझे कुछ अच्छे संदर्भ प्रदान कर सकता है तो मैं बहुत आभारी हूं।

UPDATE 1

कुछ जवाब पढ़ने के बाद, मुझे पता चला कि स्मृति वापस ओएस/व्यवस्था करने के लिए कार्यक्रम समाप्त हो जाता है के बाद, कि यदि ऐसा है तो है, क्यों हर कोई स्मृति रिसाव के बारे में इतना परवाह करने की जरूरत है, और क्यों स्मृति को रोकने में दिया जाता है रिसाव बहुत महत्वपूर्ण है?

अद्यतन 2

तो, स्मृति रिसाव रोका जाना चाहिए ताकि प्रणाली आवंटन प्रयोजनों के लिए पर्याप्त स्मृति की कमी के कारण क्रैश नहीं होता ??

अद्यतन 3

तो, सभी जवाब पढ़ने के बाद, मुझे एहसास हुआ कि स्मृति रिसाव प्रणाली दुर्घटनाओं को रोकने के लिए शांत महत्वपूर्ण मुद्दों है। लेकिन, मेरे जैसे शुरुआती व्यक्ति के लिए, मैं कैसे सुनिश्चित कर सकता हूं कि मेरा प्रोग्राम स्मृति रिसाव से पूरी तरह से मुक्त है या नहीं। मैं मुक्त करने की कोशिश करता हूं, अगर मैं मॉलोक का उपयोग कर रहा हूं, तो हटाएं, लेकिन कभी-कभी, यह गन्दा हो जाता है। क्या कोई उपकरण या विधि है जिसका उपयोग मैं यह जानने के लिए कर सकता हूं कि मेरा प्रोग्राम कोई स्मृति रिसाव कर रहा है या नहीं?

अद्यतन 4

जवाब पढ़ने के बाद, मैं अब स्मृति रिसाव मुक्त कोड, नए/हटाने के लिए, एसटीएल का अधिक उपयोग के कम उपयोग की महत्व को समझा है, आरए II, valgrind और अच्छा प्रोग्रामिंग प्रथाओं जैसे नए सामान सीखा है। सभी के लिए धन्यवाद :)

+0

अपने 2 संपादित उत्तर देने के लिए, मेरा उत्तर में 2 पैरा देख –

उत्तर

32

यह प्रति-प्रक्रिया है। एक बार आपकी प्रक्रिया समाप्त होने के बाद आवंटित स्मृति को अन्य प्रक्रियाओं (नए या मौजूदा) द्वारा उपयोग के लिए ओएस में वापस कर दिया जाता है।

आपके संपादित प्रश्न का उत्तर देने के लिए, आपकी मशीन में केवल एक सीमित मात्रा में स्मृति है। तो यदि आपके पास मेमोरी रिसाव है, तो बड़ी समस्या यह है कि स्मृति अन्य प्रक्रियाओं के उपयोग के लिए उपलब्ध नहीं है। एक माध्यमिक, लेकिन नगण्य नहीं, प्रभाव यह है कि आपकी प्रक्रिया छवि बढ़ती है, आप डिस्क पर स्वैप करेंगे और प्रदर्शन हिट हो जाएगा। अंत में आपका प्रोग्राम सिस्टम में सभी मेमोरी को समाप्त कर देगा और विफल हो जाएगा, क्योंकि यह स्वयं के लिए कोई स्मृति आवंटित करने में असमर्थ है।

यह तर्कसंगत है कि एक छोटी सी अवधि के साथ एक छोटी सी प्रक्रिया के लिए, स्मृति रिसाव सहनशील होते हैं, क्योंकि लीक की गई मात्रा मात्रा और अल्पकालिक में छोटी होगी।

this resource पर एक नज़र डालें, संभवतः आपको जितनी अधिक आवश्यकता होगी उससे अधिक जानकारी के लिए। हम यहां चर्चा कर रहे हैं गतिशील या ढेर आवंटन।

+0

मैं शब्दों बदल जाएगा कहने के लिए कि स्मृति रिसाव सहनशील हो सकता है। –

+0

अच्छा शब्द। मुझे 'स्वीकार्य' पसंद नहीं आया। मैं अब –

+1

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

9

ऑपरेटिंग सिस्टम मेमोरी ट्रैक करेगा और एक बार आपका प्रोग्राम समाप्त होने के बाद सभी मेमोरी पुनः प्राप्त होगा। इसका मतलब यह है कि आपका एप्लिकेशन कुछ आवंटित स्मृति का ट्रैक खो गया है।

ध्यान दें कि यह कुछ ऑपरेटिंग सिस्टम पर लागू नहीं हो सकता है, लेकिन किसी भी Windows/Unix/मैक प्रकार प्रणाली

+3

+1 यह इंगित करने के लिए कि यह वास्तव में प्लेटफॉर्म विशिष्ट है। –

+0

और ध्यान रखें कि यह अन्य चल रहे प्रोग्रामों पर प्रभाव डाल सकता है जो क्रैश हो सकते हैं क्योंकि वे स्मृति आवंटित नहीं कर सकते हैं! – mmmmmmmm

+0

मुझे लगता है कि आपका मतलब 32 बिट या बाद में विंडोज सिस्टम, या ओएस एक्स मैक सिस्टम, या यूनिक्स के सामान्य गैर-एम्बेडेड वेरिएंट हैं ... –

0

यह स्मृति प्रक्रिया करने के लिए सौंपा है पर मामला हो जाएगा। जब आप proccess को मारते हैं तो आप इसे वापस ले लेंगे।

2

यह एक स्मृति रिसाव है।

मूल रूप से इसका अर्थ यह है कि प्रक्रिया को नष्ट होने तक इस स्मृति को पुनः दावा नहीं किया जाएगा।

समस्या यह है कि जब पॉइंटर गुंजाइश से बाहर हो जाता है और आप स्मृति को मुक्त नहीं करते हैं तो इसे प्रक्रिया द्वारा आवंटित किया जाता है लेकिन कार्यक्रम का कोई तरीका नहीं है कि यह ज्ञात है कि यह गुंजाइश से बाहर है और अब इसकी आवश्यकता नहीं है Valgrind जैसे उपकरण का उपयोग कर)।

यह बार-बार होता है तो यह केवल एक बड़ी समस्या है। यदि ऐसा होता है तो प्रोग्राम अंततः क्रैश होने से पहले जितना अधिक चलता है उतना अधिक स्मृति का उपयोग करेगा। उपयोगकर्ताओं को यह होने से बचने के लिए नियमित रूप से एप्लिकेशन को पुनरारंभ करना होगा या यह बहुत से सिस्टम संसाधनों का उपयोग कर रहा है।

0

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

1

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

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

0

संपादित उत्तर देना -

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

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

1

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

+0

मुझे खेद है, लेकिन क्या आप अधिक विशिष्ट हो सकते हैं। –

+0

Google सी ++ मेमोरी प्रबंधन और आपको जो चाहिए उसे अधिक जानकारी प्राप्त करने में सक्षम होना चाहिए। – zooropa

+0

आप Google को ओवरराइड करना और हटा भी सकते हैं। यहां कुछ लेख दिए गए हैं जो उपयोगी हो सकते हैं। http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=40 http://www.cantrip.org/wave12.html – zooropa

4

स्मृति रिसाव का पता लगाने के लिए उपकरण हैं, उदा। Purify

5

पुन: उपकरण स्मृति

रिसाव आप विकास के लिए एक लिनक्स आधारित ऑपरेटिंग सिस्टम का उपयोग करते हैं पता लगाने के लिए, आप valgrind (http://valgrind.org/) का उपयोग कर स्मृति रिसाव का पता लगाने की कोशिश कर सकते।

valgrind --leak-check=full ./compiled_binary 

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

लाभ: यह मुफ़्त

विपक्ष है: AFAIK, यह केवल लिनक्स पर काम करता है

अद्यतन

रूप http://valgrind.org/info/platforms.html पर देखा, valgrind अन्य OSes (और प्लेटफार्मों) शामिल करने के लिए भेजा जा रहा है मैकॉक्स, फ्रीबीएसडी और नेटबीएसडी।

अद्यतन 2

(थोड़ा विषय बंद लेकिन ...)

valgrind का उपयोग कर के बारे में अच्छी बात यह है कि यह सिर्फ मेमोरी लीक के लिए जाँच की तुलना में बहुत अधिक करता है। देखें http://valgrind.org/info/tools.html

मैंने अपने सभी रात के निर्माण के खिलाफ वाल्ग्रिंड (और स्प्लिंट) चलाने के लिए बिल्डबॉट को कॉन्फ़िगर किया है, और यह अमूल्य साबित हुआ है!

+0

Valgrind के लिए +1। इसके अलावा वर्तमान वालग्रिंड एसवीएन ट्रंक में मैक ओएसएक्स समर्थन है, हालांकि मुझे इसे स्वयं करने का मौका नहीं मिला है। – Falaina

+0

बस प्रयोग के लिए, मैंने नया किया और हटा दिया नहीं। वालग्रिंड ने मुझे दिखाया कि स्मृति रिसाव और कितने बाइट थे, लेकिन यह मुझे बिल्कुल लाइन नहीं दिखाता था। बड़े कार्यक्रम में सटीक लाइन नंबर प्राप्त करना उपयोगी होगा। आपने डीबग प्रतीकों के बारे में कुछ बताया है, मैं उस पर इसका उपयोग कैसे करूं या ट्यूटोरियल करूं? –

+0

@Shawnchin: धन्यवाद, अब मैं सटीक रेखा संख्या देख सकता हूं। –

1

शुद्ध करने के साथ, आप एक मुफ्त विकल्प का प्रयास कर सकते हैं: valgrind। यह निर्धारित है कि वाल्ग्रिंड एक लिनक्स-विशिष्ट समाधान है।

16

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

लेकिन सी/सी ++ गारंटी देता है कि ओएस ऐसा करता है। कुछ प्लेटफार्मों पर यह संभव है कि स्मृति रीबूट होने तक खो जाती रहें।

तो मेमोरी लीक के साथ समस्या यह दोहरा है:

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

कई शॉर्ट चल कार्यक्रमों वास्तव में उपेक्षा स्मृति लीक क्योंकि वे जानते हैं कि यह ओएस जल्द ही द्वारा साफ कर देंगे। जहां तक ​​मुझे पता है, माइक्रोसॉफ्ट का सी ++ कंपाइलर ऐसा करता है। वे जानते हैं कि एक बार संकलक लागू होने के बाद, यह सबसे अधिक मिनटों तक चलता है। (और वे जानते हैं कि यह विंडोज़ पर चलता है, जहां ओएस प्रक्रिया समाप्त हो जाने के बाद स्मृति पुनः प्राप्त करता है) तो यह ठीक है कि यह यहां और वहां कुछ स्मृति को लीक करता है।

मेमोरी लीक से बचने के तरीके के रूप में, उन्हें न बनाएं।

हर बार जब आप नए/हटाते हैं, तो आप स्मृति को लीक करने का जोखिम लेते हैं, इसलिए नहीं है।

जब आप डेटा की एक सरणी की जरूरत है ऐसा करते हैं:

std::vector<char> vec(200); 
बजाय इस बात का

:

char* arr = new char[200]; 

पूर्व बस के रूप में कुशल है, लेकिन आप स्पष्ट रूप से करने के लिए हटाने के कॉल करने के लिए की जरूरत नहीं है इसे std::vector इसे अपने संसाधनों को आंतरिक रूप से प्रबंधित करने के लिए आरएआईआई का उपयोग करता है। और आपको वही करना चाहिए - या तो तैयार किए गए आरएआईआई कक्षाओं जैसे vector, shared_ptr, या मानक लाइब्रेरी में या बूस्ट में लगभग किसी भी अन्य वर्ग का उपयोग करके, या स्वयं लिखकर।

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

यदि कोई ऑब्जेक्ट उस मेमोरी को आवंटित करता है जिसे इसे कन्स्ट्रक्टर में आवश्यक है, और इसे विनाशक (और प्रतिलिपि/असाइनमेंट को सही तरीके से संभालता है) में रिलीज़ करता है, तो जब भी आपको इसकी आवश्यकता हो, तब आप स्टैक पर कक्षा का स्थानीय उदाहरण बना सकते हैं, और यह स्मृति को रिसाव नहीं कर सकता है।

सी ++ में मेमोरी लीक करने की कुंजी नई/डिलीट नहीं है।

+0

बहुत से लोग कहते हैं कि आपको हमेशा 'std :: vector' का उपयोग करना चाहिए, हालांकि, मुझे नहीं लगता कि यह 'लंच' के रूप में है क्योंकि हर कोई बाहर निकलना चाहता है। हां, मैं मानता हूं, आपको बहुत सारे फायदे मिलते हैं जैसा कि आप वर्णन करते हैं, हालांकि std :: iterator बस सादा बेकार है। मैं इस पर एंड्री अलेक्जेंड्रेस्कू के साथ हूं - यहां समस्या के बारे में बढ़ावा देने के लिए एक पीडीएफ है http://www.boostcon.com/site-media/var/sphene/sphwiki/attachment/2009/05/08/iterators-must -go.pdf – zebrabox

+6

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

+0

आपके उत्तर पर आप सी ++ में उदाहरण देते हैं, सी में ऐसी मेमोरी लीक को रोकने के लिए आप * ग्लिब * स्रोत के उपयोग की अनुशंसा करेंगे: http://stackoverflow.com/questions/201413/c-analog-to-stl – Alan

2

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

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

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

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

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

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

1

अद्यतन 3 का उत्तर देने के लिए आमतौर पर यह इंगित करने का एक तरीका होता है कि आपकी प्रक्रिया में कोई उत्कृष्ट स्मृति आवंटन _heapwalk (Win32 के तहत) आपको अपने सभी आवंटन के माध्यम से कदम उठाने की अनुमति देगा और आप देख सकते हैं कि कोई बकाया है या नहीं।

इसके अलावा यह संभवतः आपके मॉलोक/नई कॉल को लपेटने के लायक है ताकि जब भी ऐसा होता है तो आप प्रत्येक आवंटन की फ़ाइल और लाइन संख्या रिकॉर्ड करते हैं। फिर अपने ओवरराइड डिलीट/फ्री में आप इसे सूची से हटा दें।

, उदा (चेतावनी दी हो इस पूरी तरह से अपरीक्षित कोड है, इसलिए यह शायद बल्ले बंद काम नहीं करेगा)

struct MemoryAllocEntry 
{ 
    char* pFile; 
    char* pLine; 
}; 

extern std::map<MemoryAllocEntry> g_AllocList; 

inline void* MyMemAlloc(size_t size, char* pFile, char* pLine) 
{ 
    MemoryAllocEntry mae; 
    void* pRet = malloc(size); 
    mae.pFile = pFile; 
    mae.pLine = pLine; 

    g_AllocList[pRet] = mae; 

    return pRet; 
} 

inline void MyMemFree(void* pPtr) 
{ 
    std::map<MemoryAllocEntry>::iterator iter = g_AllocList.find(pPtr); 
    if (iter != g_AllocList.end()) 
    { 
     g_AllocList.erase(iter); 
    } 
    free(pPtr); 
} 

#ifdef _DEBUG 
    #define malloc(x) MyMemAlloc((x), __FILE__, __LINE__) 
    #define free(x) MyMemFree((x)) 
#endif 

फिर तुम सब करने की जरूरत है g_AllocList के माध्यम से कदम किसी भी बकाया आवंटन मिल रहा है। उपरोक्त स्पष्ट रूप से केवल मॉलोक और मुफ्त के लिए काम करता है लेकिन आप इसे नए के लिए काम कर सकते हैं और साथ ही हटा सकते हैं (एमएफसी इसे उदाहरण के लिए करता है)।

1

अपने प्रश्न का उत्तर में, और अद्यतन 1 ,:

नहीं सभी ऑपरेटिंग सिस्टम अलग प्रक्रियाओं की धारणा कभी नहीं स्वचालित रूप से साफ बातें करेंगे ही समर्थन करती है, इसलिए।

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

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

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

सी का उपयोग कर निम्न-स्तर वाले एम्बेडेड प्रोग्रामर स्टार्टअप पर सब कुछ आवंटित करके स्मृति लीक से बचते हैं। सी प्रोग्रामर संभावित मेमोरी लीक से बचने के लिए एलोका() के साथ स्टैक आवंटन का भी उपयोग कर सकते हैं (लेकिन उन्हें यह समझने की आवश्यकता है कि यह वास्तव में कैसे काम करता है)।

2

कई अंक जोड़ने के लिए:

  1. सही ढंग से काम फार्म शुरुआत को जानें - मुक्त स्मृति, यह बुरी आदत ठीक करने के लिए बहुत कठिन है।
  2. मेमोरी अद्वितीय संसाधन नहीं है जिसे नए/हटाए जाने से प्रबंधित या प्रबंधित किया जाना चाहिए।

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

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

3

सी ++ प्रोग्रामर, सबसे अच्छा सलाह मैं तुम्हें कैसे 'नई' और "हटाएँ" बयान आप लिखते हैं की संख्या को कम करने के लिए सीखने के लिए किया जाएगा करने के लिए दे सकता है के लिए एक नया रूप। यदि आपके पास कंपाइलर स्टैक पर स्थानीय रूप से आपकी ऑब्जेक्ट्स बनाते हैं, तो यह आपके लिए स्मृति का प्रबंधन करेगा, ऑब्जेक्ट्स को स्वचालित रूप से हटाए जाने के बाद वे स्कोप से बाहर निकल जाएंगे।

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

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

+0

+1 आरएआईआई परिचय ... निश्चित रूप से अब उसमें देखेंगे ... –

0

जब कार्यक्रम खिड़कियों में खत्म यह न केवल स्मृति को रिहा लेकिन सभी हैंडल खुला (मुझे ठीक कर लें मैं गलत हूँ)

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