जब आप एक सी एप्लिकेशन से बाहर निकलते हैं, तो क्या मॉलोक-एड मेमोरी स्वचालित रूप से मुक्त हो जाती है?


92

मान लीजिए कि मेरे पास निम्नलिखित C कोड है:

int main () {
  int *p = malloc(10 * sizeof *p);
  *p = 42;
  return 0;  //Exiting without freeing the allocated memory
}

जब मैं उस C प्रोग्राम को संकलित और निष्पादित करता हूं, अर्थात मेमोरी में कुछ स्थान आवंटित करने के बाद, क्या वह मेमोरी मुझे अभी भी आवंटित की जाएगी (यानी मूल रूप से स्पेस लेने के बाद) मैं एप्लिकेशन से बाहर निकलता हूं और प्रक्रिया समाप्त हो जाती है?


9
यह आपकी याददाश्त को साफ करने के लिए "अच्छी शैली" है, इसलिए नहीं कि आप एक ऐसे ओएस पर चल सकते हैं जिसमें संरक्षित मेमोरी नहीं है (जो नीचे मुख्य सुझाव है), लेकिन क्योंकि इससे संभावना बढ़ जाती है कि आपको मेमोरी लीक मिल जाए, और बनी रहे आपका कोड दुबला और सही है ...
मैट जॉइनर

जवाबों:


111

यह ऑपरेटिंग सिस्टम पर निर्भर करता है। अधिकांश आधुनिक (और सभी प्रमुख) ऑपरेटिंग सिस्टम मेमोरी को उस प्रोग्राम से मुक्त नहीं करेंगे जब यह समाप्त होता है।

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


16
मुझे एक बार एम्बेडेड प्लेटफॉर्म पर win98 का ​​सामना करना पड़ा, और उस अनुभव के आधार पर, मैं कह सकता हूं कि प्रोग्राम बंद होने पर यह मेमोरी को खाली नहीं करता है।
सैन जैसिंटो

8
@ यह एक उदाहरण था। इसके अलावा, YAGNI और मैला कोडिंग के बीच एक रेखा है। मुक्त संसाधन इसे पार नहीं करते हैं। YAGNI सिद्धांत भी सुविधाओं पर लागू होने के लिए था, न कि कोड जो प्रोग्राम को सही ढंग से काम करता हो। (और स्मृति को मुक्त करना बग नहीं है)।
याकूब

5
+1: सबसे महत्वपूर्ण बात यह है कि स्मृति प्रबंधन याकूबी के रूप में काफी सही रूप से बताता है: "ऑपरेटिंग सिस्टम की एक विशेषता" । जब तक मैं गलत नहीं हूं, प्रोग्रामिंग भाषा यह परिभाषित नहीं करती है कि कार्यक्रम निष्पादन से पहले या बाद में क्या होता है।
15

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

6
कोई भी एसओ पर मेमोरी लीक का प्रस्ताव सभी प्रतिष्ठा और बैज से छीन लिया जाना चाहिए
उल्टी

53

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

अपने कार्यक्रम को स्पष्ट रूप से अपने संसाधनों से मुक्त करना वैसे भी विभिन्न कारणों से अच्छा अभ्यास हो सकता है, जैसे:

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

हालांकि, यहां फ्रीजिंग मेमोरी को सक्षम करने का एक कारण है: कुशल शटडाउन । उदाहरण के लिए, मान लीजिए कि आपके एप्लिकेशन में मेमोरी में एक बड़ा कैश है। यदि यह बाहर निकलता है तो यह पूरी कैश संरचना के माध्यम से जाता है और एक बार में एक टुकड़ा मुक्त करता है, जो कोई उपयोगी उद्देश्य नहीं देता है और संसाधनों को बर्बाद करता है। विशेष रूप से, उस मामले पर विचार करें जहां आपके कैश वाले मेमोरी पेज को ऑपरेटिंग सिस्टम द्वारा डिस्क पर स्वैप किया गया है; संरचना को चलने और इसे मुक्त करने से आप उन सभी पृष्ठों को एक साथ सभी मेमोरी में वापस ला रहे हैं , जो बिना किसी वास्तविक लाभ के लिए महत्वपूर्ण समय और ऊर्जा बर्बाद कर रहे हैं, और संभवतः सिस्टम पर अन्य कार्यक्रमों को स्वैप करने के लिए भी पैदा कर रहे हैं!

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


11

इस सूत्र को अंतिम पोस्ट के इतने समय बाद पोस्ट करने के लिए मेरी माफी।

एक अतिरिक्त बिंदु। सभी प्रोग्राम इसे ग्रेसफुल एग्जिट के लिए नहीं बनाते हैं। क्रैश और ctrl-C, आदि अनियंत्रित तरीके से बाहर निकलने के लिए एक कार्यक्रम का कारण बनेंगे। यदि आपका ओएस आपके ढेर को मुक्त नहीं करता है, तो अपने स्टैक को साफ करें, स्थिर चर को हटा दें, आदि, आप अंततः अपने सिस्टम को मेमोरी लीक या खराब से क्रैश कर देंगे।

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

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

किसी को भी इस डिजाइन पर टिप्पणी करने के लिए परवाह है?


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

8
Stackoverflow एक मंच नहीं है; एक पुराने प्रश्न का उत्तर देने में कुछ भी गलत नहीं है। meta.stackexchange.com/questions/20524/reviving-old-questions
mk12

6

यहां क्या हो रहा है ( एक आधुनिक ओएस में ), यह है कि आपका कार्यक्रम अपनी "प्रक्रिया" के अंदर चलता है। यह एक ऑपरेटिंग सिस्टम इकाई है जो अपने स्वयं के एड्रेस स्पेस, फाइल डिस्क्रिप्टर आदि के साथ संपन्न होती है। आपकी mallocकॉल "हीप", या बिना मेमोरी वाले पेजों से मेमोरी आवंटित कर रही है जो आपकी प्रक्रिया को सौंपा गया है।

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

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

यह सब कहा, जैसा कि अन्य सभी उत्तरदाताओं ने ध्यान दिया है, इस पर भरोसा करना अच्छा अभ्यास नहीं है:

  1. संसाधनों की देखभाल के लिए आपको हमेशा प्रोग्रामिंग होना चाहिए, और सी में इसका मतलब है कि मेमोरी भी। आप अपने कोड को किसी लाइब्रेरी में एम्बेड कर सकते हैं, या यह आपकी अपेक्षा से अधिक लंबा चल सकता है।
  2. कुछ OS (पुराने वाले और शायद कुछ आधुनिक एम्बेडेड वाले) ऐसी कठिन प्रक्रिया सीमाओं को बनाए नहीं रख सकते हैं, और आपके आवंटन दूसरों के पता रिक्त स्थान को प्रभावित कर सकते हैं।

4

हाँ। ओएस संसाधनों को साफ करता है। खैर ... NetWare के पुराने संस्करण नहीं थे।

संपादित करें: जैसा कि सैन जैसिंटो ने बताया, निश्चित रूप से सिस्टम (नेटवेअर से अलग) हैं जो ऐसा नहीं करते हैं। फेंक-दूर के कार्यक्रमों में भी, मैं सिर्फ आदत को बनाए रखने के लिए सभी संसाधनों को मुक्त करने की आदत बनाने की कोशिश करता हूं।


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

@ शान जैसिंटो: यह एक अच्छी बात है। यही कारण है कि मैंने नेटवेअर का संदर्भ दिया, लेकिन यह शायद स्पष्टीकरण का उपयोग कर सकता है। मैं इसे थोड़ा संपादित करूँगा।
मार्क विल्किंस

3
@ एसओएस डॉस एक मल्टी-टास्किंग ओएस नहीं है - जब एक डॉस प्रोग्राम (टीएसआर को छोड़कर) समाप्त होता है, तो अगले प्रोग्राम को लोड करने के लिए सभी मेमोरी उपलब्ध होती है।

@ रिमाइंडर के लिए धन्यवाद, लेकिन मैं टीएसआर-जैसे कार्यक्रम का जिक्र कर रहा था जो कि जब कोई घटना होती है, तो एम्बेडेड सिस्टम के लिए एक सामान्य उपयोग होता है। फिर भी, आपकी विशेषज्ञता और स्पष्टीकरण के लिए धन्यवाद, जहां मैं विफल रहा :)
San Jacinto

2

हाँ, ऑपरेटिंग सिस्टम प्रक्रिया समाप्त होने पर सभी मेमोरी रिलीज़ करता है।


मैं नहीं देखता कि यह क्यों अस्वीकृत किया गया था। जब प्रक्रिया मरता malloc'ed स्मृति जारी किया जाएगा (विकिपीडिया malloc की Definiton तो कहते हैं)
Arve

7
विकिपीडिया अस्तित्व में प्रत्येक ओएस के लिए मैनुअल नहीं है। अधिकांश आधुनिक ओएस मेमोरी को पुनः प्राप्त करेंगे, लेकिन सभी (और विशेष रूप से सभी पुराने नहीं) करते हैं। इसके साथ जोड़ें, mallocकेवल वादा कर सकता है कि सी मेमोरी के साथ क्या करेगा; डिजाइन के अनुसार, C, C के बाहर व्यवहार के संबंध में कुछ भी गारंटी नहीं देता है। यदि एप्लिकेशन अप्रत्याशित रूप से मर जाता है, तो किए गए रनटाइम लाइब्रेरी के किसी भी वादे शून्य और शून्य हैं, क्योंकि यह अब उनके लिए जीवित नहीं है।
cHao

2

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

बस यह सुनिश्चित करें कि आप इसे मुक्त कर सकते हैं, यह आपको बाद में बहुत समय बचा सकता है जब आप इसे एक बड़ी परियोजना में एकीकृत करना चाहते हैं।


0

यह वास्तव में ऑपरेटिंग सिस्टम पर निर्भर करता है, लेकिन सभी ऑपरेटिंग सिस्टम के लिए आप कभी भी मुठभेड़ करेंगे, प्रक्रिया से बाहर निकलने पर मेमोरी आवंटन गायब हो जाएगा।


0

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

जहां तक, या चाहे, मैंने पाया कि W98 में, असली सवाल 'कब' था (मैंने इस पर जोर देने वाली पोस्ट नहीं देखी थी)। एक छोटा सा टेम्प्लेट प्रोग्राम (मिडी SysEx इनपुट के लिए, विभिन्न मॉलोकैड स्पेस का उपयोग करके) WndProc के WM_DESTROY बिट में मेमोरी को फ्री करेगा, लेकिन जब मैंने इसे एक बड़े प्रोग्राम में ट्रांसप्लांट किया तो यह बाहर निकलने पर क्रैश हो गया। मुझे लगता है कि इसका मतलब है कि मैं मुक्त करने की कोशिश कर रहा था कि ओएस पहले से ही बड़ी सफाई के दौरान मुक्त हो गया था। अगर मैंने इसे WM_CLOSE पर किया, तो विनास्टविंडो () कहा जाता है, यह सब ठीक काम करता है, तत्काल स्वच्छ निकास।

हालांकि यह बिल्कुल मिडी बफ़र्स जैसा नहीं है, इसमें समानता है कि प्रक्रिया को अक्षुण्ण रखना, पूरी तरह से साफ करना, फिर बाहर निकलना सबसे अच्छा है। मामूली मेमोरी चंक्स के साथ यह बहुत तेज़ है। मैंने पाया कि कई छोटे बफ़र्स ने ऑपरेशन में बहुत तेजी से काम किया और कम बड़े लोगों की तुलना में सफाई की।

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

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