मेमोरी लीक्स कितनी दूर जा सकते हैं?


118

मैं कई बार मेमोरी लीक्स में दौड़ चुका हूं। आमतौर पर जब मैं ऐसा कर रहा होता हूं तो mallocकोई कल नहीं होता, या FILE *गंदे कपड़े धोने जैसे झूलने लगते हैं । मैं आम तौर पर मानता हूं (पढ़ें: आशा है कि सख्त) कि सभी मेमोरी कम से कम साफ हो जाती है जब प्रोग्राम समाप्त हो जाता है। क्या कोई ऐसी स्थिति है जहां लीक की गई मेमोरी को प्रोग्राम समाप्त होने या क्रैश होने पर एकत्र नहीं किया जाएगा?

यदि उत्तर भाषा से भाषा में व्यापक रूप से भिन्न होता है, तो आइए C (++) पर ध्यान केंद्रित करें।

कृपया वाक्यांश के हाइपरबोलिक उपयोग पर ध्यान दें, 'जैसे कल नहीं है', और 'झूलने ... गंदे कपड़े धोने की तरह'। असुरक्षित * malloc* आईएनजी उन लोगों को चोट पहुंचा सकता है जिन्हें आप प्यार करते हैं। इसके अलावा, कृपया गंदे कपड़े धोने के साथ सावधानी बरतें।


3
यदि आप लिनक्स या विंडोज जैसे "आधुनिक" ओएस के साथ चल रहे हैं, तो प्रोग्राम समाप्त होने पर ओएस स्वयं किसी भी अप्रकाशित मेमोरी को हल करेगा।
ओलिवर चार्ल्सवर्थ

60
मॉलॉक-आईएनजी के बजाय जैसे कि कल नहीं है, नाटक करने की कोशिश करें कि कल है और अपनी स्मृति का ध्यान रखें!
विलियम पर्ससेल

8
@WilliamPursell आह, तो आप कह रहे हैं कि callocजैसे कोई कल नहीं होना चाहिए । अति उत्कृष्ट।
दिल्लियोटमैट्रिक्स

8
"यदि उत्तर भाषा से भाषा में व्यापक रूप से भिन्न होता है, तो c (++) पर ध्यान केंद्रित करने देता है।" c और c ++ समान भाषा नहीं हैं!
Johnsyweb

11
@zhermes: C और C ++ के बारे में टिप्पणी करें कि अलग-अलग भाषाएं आपके विचार से अधिक छिपती हैं ... C ++ में आप स्वचालित रूप से स्वचालित भंडारण अवधि के साथ वस्तुओं का लाभ ले पाएंगे, RAII मुहावर का पालन करेंगे ... आप इन वस्तुओं को स्मृति का ध्यान रखने दें। आपके लिए प्रबंधन।
लिहो

जवाबों:


111

जब वे बाहर निकलते हैं तो ऑपरेटिंग सिस्टम सभी संसाधनों को प्रक्रियाओं से मुक्त करता है।

यह उन सभी संसाधनों पर लागू होता है जो ऑपरेटिंग सिस्टम बनाए रखता है: मेमोरी, ओपन फाइल्स, नेटवर्क कनेक्शन, विंडो हैंडल ...

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

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


5
RTOS में एक सामान्य प्रतिमान एकल-प्रक्रिया, कई थ्रेड मॉडल और 'कार्य' के बीच कोई मेमोरी सुरक्षा नहीं है। आमतौर पर एक ढेर है। यह निश्चित रूप से है कि कैसे VxWorks काम करते थे - और शायद अभी भी करता है।
मार्को

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

1
@ मार्को: vxWorks के हालिया संस्करण अब RTP (वास्तविक समय प्रक्रियाओं) का समर्थन करते हैं जो मेमोरी सुरक्षा का समर्थन करते हैं।
जेवियर टी।

20
"ऑपरेटिंग सिस्टम बाहर निकलने पर प्रक्रियाओं द्वारा आयोजित सभी संसाधनों को मुक्त कर देता है।" सख्ती से सच नहीं। उदाहरण के लिए, (कम से कम) लिनक्स, SysV सेमाफोर और अन्य IPC ऑब्जेक्ट को प्रक्रिया से बाहर निकलने पर साफ नहीं किया जाता है। इसलिए ipcrmमैन्युअल क्लीनअप, linux.die.net/man/8/ipcrm के लिए है

7
साथ ही, यदि किसी ऑब्जेक्ट में एक अस्थायी फ़ाइल है जिसे वह रखता है, तो यह स्पष्ट रूप से बाद में साफ नहीं किया जाएगा।
मूइंग डक

47

सी मानक निर्दिष्ट नहीं करता है कि mallocप्रोग्राम द्वारा समाप्त होने पर द्वारा आवंटित मेमोरी जारी की जाती है। यह ऑपरेटिंग सिस्टम द्वारा किया गया है और सभी OSes (आमतौर पर ये एम्बेडेड दुनिया में हैं) प्रोग्राम को समाप्त होने पर मेमोरी को रिलीज़ करते हैं।


20
यह कमोबेश इसलिए है क्योंकि C मानक C कार्यक्रमों के बारे में बात करता है, न कि ऑपरेटिंग सिस्टम जिन पर C चलता है ...
vonbrand

5
@vonbrand C मानक में एक पैराग्राफ हो सकता है जो कहता है कि जब mainरिटर्न द्वारा आवंटित सभी मेमोरी mallocको जारी किया जाता है। उदाहरण के लिए यह कहता है कि प्रोग्राम समाप्ति से पहले सभी खुली फाइलें बंद हो जाती हैं। मेरे लिए आवंटित स्मृति के लिए malloc, यह केवल निर्दिष्ट नहीं है। अब निश्चित रूप से ओएस के बारे में मेरा वाक्य बताता है कि आमतौर पर क्या किया जाता है जो मानक निर्धारित नहीं करता है, क्योंकि यह इस पर कुछ भी निर्दिष्ट नहीं करता है।
ahउह

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

2
@ouah: " जब मुख्य रिटर्न ..."। यह एक धारणा है। हमें " यदि मुख्य रिटर्न ..." पर विचार करना है । std::atexitकार्यक्रम समाप्ति के माध्यम से भी विचार करता है std::exit, और फिर वहाँ भी है std::abortऔर (C ++ विशिष्ट) std::terminate
MSalters

@ouah: यदि वह शामिल किया गया था, atexitतो उपयोग करने योग्य नहीं होगा। :-)
आर .. गिटहब स्टॉप हेल्पिंग IC

28

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

तो तकनीकी रूप से कार्यक्रम समाप्त हो जाता है , लेकिन क्योंकि यह अभी भी स्मृति पर रहता है, कोई भी स्मृति रिसाव तब तक जारी नहीं किया जाएगा जब तक आप कार्यक्रम को अनलोड नहीं करते।

तो आप इस पर विचार कर सकते हैं कि ओएसिस के अलावा एक और मामला है या तो स्मृति को पुनः प्राप्त नहीं करना है क्योंकि यह छोटी गाड़ी है या क्योंकि एम्बेडेड ओएस ऐसा करने के लिए डिज़ाइन किया गया है।

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


यह वास्तव में दिलचस्प है, ऐतिहासिक नोट के लिए धन्यवाद! क्या आपको पता है कि अगर प्रतिमान की जरूरत नहीं थी, तो स्मृति को मुक्त करना बहुत अधिक महंगा होने के कारण था? या विकल्प अभी तक कभी नहीं सोचा गया था?
Dil लिथियमMatrix

1
@zhermes: यह कम्प्यूटेशनल रूप से असंभव था, क्योंकि DOS ने TSR के लिए मेमोरी एलोकेशन को ट्रैक नहीं किया था। परिभाषा से बहुत ज्यादा: लक्ष्य रेजिडेंट रहना था । यदि आप चाहते थे कि आपकी TSR कुछ नहीं बल्कि सभी मेमोरी को मुक्त करे, तो यह आप पर निर्भर था कि आप क्या मुफ्त करें।
MSalters

2
@zhermes: DOS (CP / M की तरह, इसके पूर्वज) वह नहीं था जिसे आप आधुनिक अर्थों में ऑपरेटिंग सिस्टम कहेंगे। यह वास्तव में आई / ओ उपयोगिताओं का एक संग्रह था जिसे एक मानक प्रोसेसर के साथ बंडल करके मानक तरीके से बुलाया जा सकता था जो आपको एक समय में एक कार्यक्रम चलाने देगा। प्रक्रियाओं की कोई धारणा नहीं थी, और स्मृति न तो आभासी थी और न ही संरक्षित थी। TSR एक उपयोगी हैक थे जो सिस्टम को 64K स्थान तक ले जाने के बारे में बता सकते थे और खुद को बीच में रोकेंगे ताकि उन्हें कॉल आए।
ब्लरफ्ल

8

जैसा कि अन्य लोगों ने कहा है, अधिकांश ऑपरेटिंग सिस्टम प्रक्रिया समाप्ति पर आवंटित स्मृति को पुनः प्राप्त करेंगे (और शायद नेटवर्क सॉकेट, फ़ाइल हैंडल आदि जैसे अन्य संसाधन)।

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

कहानी का नैतिक, हमेशा खुद के बाद साफ। बातें मत करो। आप के बाद सफाई ओएस पर भरोसा मत करो। अपने आप के बाद साफ करो।


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

1
सी ++ में, विध्वंसक कार्यक्रम की समाप्ति पर बुलाया जाएगा (जब तक कि कुछ कम-से-उज्ज्वल kill -9प्रशंसक नहीं दिखाता ...)
वॉनब्रांड

@vonbrand True, लेकिन अगर हम गतिशील वस्तुओं के साथ लीक के बारे में बात कर रहे हैं, तो वे विनाशकारी घटित नहीं होंगे। दायरे से बाहर जाने वाली वस्तु एक कच्चा सूचक है, और इसका विध्वंसक कोई विकल्प नहीं है। (बेशक, इस मुद्दे को कम करने के लिए RAII ऑब्जेक्ट देखें ...)
आंद्रे कोस्तूर

1
RAII के साथ समस्या यह है कि यह प्रक्रिया से बाहर निकलने पर वस्तुओं को निपटाने पर जोर देती है जो वास्तव में छुटकारा पाने के लिए महत्वपूर्ण नहीं है। DB कनेक्शन जिनसे आप सावधान रहना चाहते हैं, लेकिन सामान्य मेमोरी को ओएस द्वारा साफ किया जाता है (यह कहीं बेहतर काम करता है)। यह समस्या एक ऐसे कार्यक्रम के रूप में प्रकट होती है जो स्मृति द्वारा पृष्ठांकित होने पर बाहर निकलने के लिए पूरी तरह से आयु लेता है । इसे हल करना गैर-तुच्छ भी है ...
डोनल फेलो

@vonbrand: यह इतना आसान नहीं है। std::exitकॉल डक्टर्स, std::abortनहीं करेंगे, बिना अपवाद के अपवाद हो सकते हैं।
MSalters

7

यह भाषा की तुलना में ऑपरेटिंग सिस्टम पर निर्भर होने की अधिक संभावना है। अंततः किसी भी भाषा में किसी भी कार्यक्रम को ऑपरेटिंग सिस्टम से मेमोरी मिल जाएगी।

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


क्या आप सरलीकृत OS के मामले में कर्नेल की मेमोरी पिक्चर को स्क्रू कर सकते हैं? .. जैसे, बिना मल्टीटास्किंग के भी वो ऑपरेटिंग सिस्टम।
23

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

1GiB का @vonbrand दुर्लभ उपयोग सामान्य रूप से तब तक समस्या नहीं है (जब तक आपको भौतिक मेमोरी बहुत अधिक मिल गई है) क्योंकि आधुनिक ऑपरेटिंग सिस्टम बिट्स को वर्तमान में सक्रिय नहीं कर सकते हैं। समस्या तब आती है जब आपको भौतिक मेमोरी की तुलना में सक्रिय मेमोरी में अधिक वर्चुअल मेमोरी मिली है, जिसमें इसे होस्ट करना है।
डोनल फेलो

5

यदि प्रोग्राम को कभी डायनेमिक कंपोनेंट ("प्लगइन") में बदल दिया जाता है, जिसे किसी अन्य प्रोग्राम के एड्रेस स्पेस में लोड किया जाता है, तो यह समस्याग्रस्त हो जाएगा, यहां तक ​​कि सुव्यवस्थित मेमोरी मैनेजमेंट वाले ऑपरेटिंग सिस्टम पर भी। हमें कोड को कम सक्षम प्रणालियों में पोर्ट किए जाने के बारे में सोचने की ज़रूरत नहीं है।

दूसरी ओर, सभी मेमोरी जारी करने से प्रोग्राम के क्लीनअप के प्रदर्शन पर असर पड़ सकता है

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

एक उचित समाधान यह है कि उसमें क्षमता हो और उसे परीक्षण मामलों से आच्छादित किया जाए, लेकिन इसे उत्पादन कोड में बंद कर दें ताकि एप्लिकेशन तेजी से समाप्त हो जाए।


5

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

संपादित करें: आपको मेमोरी लीक को साफ करने की आवश्यकता है यदि वे उस स्थान पर हैं जहां वे जमा होंगे, जैसे छोरों में। मेमोरी लीक की बात मैं कर रहा हूँ जो प्रोग्राम के दौरान लगातार समय में बनते हैं, अगर आपके पास किसी भी अन्य प्रकार की लीक है तो यह जल्दी या बाद में एक गंभीर समस्या होगी।

तकनीकी शब्दों में यदि आपकी लीक मेमोरी 'जटिलता' O (1) के हैं तो वे ज्यादातर मामलों में ठीक हैं, O (logn) पहले से ही अप्रिय (और कुछ मामलों में घातक) और O (N) + असहनीय।


3

POSIX अनुरूप सिस्टम पर साझा की गई मेमोरी तब तक बनी रहती है जब तक कि shm_unlink को कॉल नहीं किया जाता है या सिस्टम को रिबूट नहीं किया जाता है।


2

यदि आपके पास इंटरप्रोसेस संचार है, तो यह अन्य प्रक्रियाओं को पूरा नहीं कर सकता है और प्रोटोकॉल के आधार पर संसाधनों को पूरा नहीं कर सकता है।

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.