2011-10-30 20 views
17

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

संबंधित नोट पर, हर्ब सटर का कहना है कि सी ++ मेमोरी त्रुटियों को संभालना व्यर्थ है, क्योंकि सिस्टम वास्तव में एक अपवाद होने से पहले पेजिंग के स्पैम में जाएगा। क्या यह malloc पर भी लागू होता है?

+3

मुझे लगता है कि आपको सी ++ में मॉलोक का उपयोग नहीं करना चाहिए: http://stackoverflow.com/questions/184537/in-what-cases-do-i-use-malloc-vs-new – lc2817

+1

@ lc2817 आपको केवल उपयोग करना चाहिए malloc अगर आप एक सी इंटरफ़ेस के साथ कोड लिख रहे हैं (यानी कार्य जो सी से उपयोग किए जाते हैं लेकिन सी ++ में लिखे गए हैं) ** और ** सी कोड उस स्मृति को मुक्त करने के लिए ज़िम्मेदार है। इस परिशुद्धता के लिए –

+0

@WTP धन्यवाद। हालांकि, मुझे नहीं पता कि यह मामला यहां है या नहीं। – lc2817

उत्तर

32

Linux manuals का हवाला देते हुए:

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

# echo 2 > /proc/sys/vm/overcommit_memory 
: मामले लिनक्स परिस्थितियों में कार्यरत है में यह कम अचानक कम करने के लिए कुछ बेतरतीब ढंग से उठाया प्रक्रियाओं, और इसके अलावा कर्नल संस्करण पर्याप्त हाल है, एक तरह एक आदेश का उपयोग कर इस overcommitting व्यवहार बंद कर सकते हैं वांछनीय होगा जहां

आपको NULL वापसी की जांच करनी चाहिए, खासकर 32-बिट सिस्टम पर, क्योंकि प्रक्रिया पता स्थान रैम से बहुत पहले समाप्त हो सकता है: उदाहरण के लिए 32-बिट लिनक्स पर, उपयोगकर्ता प्रक्रियाओं में 2 जी का उपयोग करने योग्य पता स्थान हो सकता है - कुल रैम के 4 जी से अधिक के विपरीत 3 जी। 64-बिट सिस्टम पर malloc रिटर्न कोड की जांच करने के लिए बेकार हो सकता है, लेकिन किसी भी तरह से अच्छा अभ्यास माना जा सकता है, और यह आपके प्रोग्राम को अधिक पोर्टेबल बनाता है। और, याद रखें, शून्य सूचक का निश्चय करना निश्चित रूप से आपकी प्रक्रिया को मारता है; कुछ स्वैपिंग की तुलना में ज्यादा चोट नहीं पहुंची हो सकती है।

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

डिफ़ॉल्ट सी ++ ऑपरेटर new अक्सर malloc() द्वारा नियोजित उसी आवंटन तंत्र पर एक रैपर होता है।

+8

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

+2

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

+0

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

5

लिनक्स पर, आप वास्तव में कर्नेल के overallocation रणनीति की वजह से mallocNULL लौटने पर भरोसा नहीं कर सकते, तो पर्याप्त स्मृति उपलब्ध नहीं है, लेकिन आप अभी भी क्योंकि कुछ परिस्थितियों में इसके लिए जांच होनी चाहिए mallocहोगा वापसी NULL, उदा जब आप कुल मशीन में उपलब्ध होने की तुलना में अधिक स्मृति मांगते हैं। लिनक्स malloc(3) मैनपेज कुल मिलाकर "वास्तव में खराब बग" कहता है और इसे बंद करने के तरीके पर सलाह शामिल है।

मैंने कभी भी इस व्यवहार के बारे में अन्य यूनिक्स रूपों में भी नहीं सुना है।

"पेजिंग के स्पैम" के लिए, यह मशीन सेटअप पर निर्भर करता है। उदाहरण के लिए, मैं लैपटॉप लिनक्स प्रतिष्ठानों पर एक स्वैप विभाजन सेट अप नहीं करता हूं, क्योंकि आपके द्वारा डरने वाले सटीक व्यवहार को हार्ड डिस्क को मारना पड़ सकता है। मुझे अभी भी सी/सी ++ प्रोग्राम पसंद आएंगे जो मैं malloc वापसी मूल्यों की जांच करने के लिए चलाता हूं, उचित त्रुटि संदेश देता हूं और जब संभव हो तो खुद को साफ कर लेता हूं।

+1

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

1

देखने का एक वैकल्पिक दृष्टिकोण से इस देखने के लिए:

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

2

malloc की वापसी के लिए जांच करने से आपके आवंटन को सुरक्षित या कम त्रुटि प्रवण बनाने में आपकी सहायता नहीं होती है। यह एक जाल भी हो सकता है यदि यह एकमात्र परीक्षण है जिसे आप कार्यान्वित करते हैं।

0 के तर्क के साथ कहा जाने वाला मानक malloc को एक अद्वितीय पता लौटने की अनुमति देता है, जो एक शून्य सूचक नहीं है और जिसे आपके पास पहुंचने का अधिकार नहीं है। इसलिए यदि आप परीक्षण करते हैं कि वापसी 0 है लेकिन malloc, calloc या realloc पर तर्कों का परीक्षण न करें तो आपको बाद में एक सेगफॉल्ट का सामना करना पड़ सकता है।

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

लोग तब उस त्रुटि स्थिति के जटिल कैप्चर के साथ अपने कोड को सजाने के लिए जाते हैं जो कई लाइनें, perror और उस तरह की चीजें कर रही हैं, जो कोड की पठनीयता पर असर डाल सकती हैं।

मुझे लगता है कि यह "malloc की वापसी की जांच करें" बहुत अधिक है, कभी-कभी यहां तक ​​कि काफी हद तक बचाव भी किया जाता है। अन्य चीजें अधिक महत्वपूर्ण हैं:

  • हमेशा चर, हमेशा प्रारंभ करें। सूचक चर के लिए यह महत्वपूर्ण है, चीजें बहुत खराब होने से पहले कार्यक्रम को अच्छी तरह से दुर्घटनाग्रस्त होने दें। struct में अनियंत्रित सूचक सदस्य त्रुटियों का एक महत्वपूर्ण कारण हैं जो खोजना मुश्किल है।
  • हमेशा malloc और कं के लिए तर्क की जाँच करता है, तो यह एक संकलन समय निरंतर sizof toto है कि कोई समस्या नहीं हो सकता है, लेकिन हमेशा सुनिश्चित करें कि आपके वेक्टर आवंटन ठीक से शून्य मामले संभालती है।

malloc की वापसी के लिए जांचने के लिए एक आसान बात यह है कि इसे memset(malloc(n), 0, 1) जैसे कुछ के साथ लपेटें। यह पहले बाइट में 0 लिखता है और malloc में कोई त्रुटि होती है या n0 से शुरू होने के लिए अच्छी तरह से क्रैश होता है।

+0

आइए बस यह कहें कि "बार में शून्य सूचक अपवाद" की तुलना में उपयोगकर्ता को "लाइन पर ढेर से बाहर" कहने के लिए बहुत अच्छा लगता है; इसके लिए मॉलोक के लिए एक साधारण (मैक्रो?) रैपर पर्याप्त होगा। अगर कोई हास्यास्पद मात्रा में स्मृति का उपयोग करता है और 32 बिट सिस्टम पर 2 जी से अधिक का उपयोग करने की उम्मीद कर सकता है। –

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