2009-08-20 13 views
10

तो मैं अपने विकास के साथ क्यूटी का बहुत उपयोग करता हूं और इसे प्यार करता हूं। क्यूटी वस्तुओं के साथ सामान्य डिजाइन पैटर्न उन्हें new का उपयोग करके आवंटित करना है।पकड़ने के साथ नीति std :: bad_alloc

बहुत सारे उदाहरण (विशेष रूप से क्यूटी डिजाइनर द्वारा उत्पन्न कोड) std::bad_alloc अपवाद के लिए पूरी तरह से जांच नहीं करते हैं। चूंकि ऑब्जेक्ट आवंटित (आमतौर पर विजेट और ऐसे) छोटे होते हैं, यह शायद ही कभी एक समस्या है। आखिरकार, यदि आप 20 बाइट्स जैसे कुछ आवंटित करने में विफल रहते हैं, तो हालात समस्या का समाधान करने के लिए आप इतना कुछ नहीं कर सकते हैं।

वर्तमान में, मैंने कोशिश की/पकड़ में आवंटन "बड़े" (पृष्ठ या दो आकार से ऊपर कुछ भी) लपेटने की नीति अपनाई है। यदि यह विफल रहता है, तो मैं उपयोगकर्ता को एक संदेश प्रदर्शित करता हूं, जो कुछ भी छोटा है, मैं सिर्फ std::bad_alloc अपवाद के साथ ऐप को क्रैश कर दूंगा।

तो, मुझे आश्चर्य है कि इस पर विचारों के स्कूल इस पर क्या हैं?

क्या प्रत्येक new ऑपरेशन की जांच करना अच्छी नीति है? या केवल मुझे उम्मीद है कि असफल होने की संभावना है?

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

उत्तर

17

समस्या "पकड़ने के लिए" नहीं है, लेकिन "अपवाद कैच होने पर क्या करना है"।

आप की जांच करने के बजाय try catch साथ लपेटकर का चाहते हैं तो आप बेहतर उपयोग करेंगे

#include <new> 
    x = new (std::nothrow) X(); 
    if (x == NULL) { 
     // allocation failed 
    } 

मेरे सामान्य अभ्यास

  • गैर इंटरैक्टिव कार्यक्रम में

    , मुख्य स्तर एक प्रदर्शन एक पर पकड़ है वहां पर्याप्त त्रुटि संदेश है।

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

असाधारण रूप से, ऐसे अन्य स्थान हैं जहां एक पकड़ सार्थक है, लेकिन यह दुर्लभ है।

+1

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

+1

इतना नहीं "क्या करना है", लेकिन "क्या आप कुछ भी कर सकते हैं" – jalf

+0

यदि आप इसे काफी अधिक पकड़ते हैं, तो कुछ स्मृति को अवांछित ढेर के दौरान मुक्त किया जा सकता है। आप यह सुनिश्चित कर सकते हैं कि किसी नए_हैंडर या ट्रिक्स जैसे 'int flag = false; कोशिश करें {वेक्टर वी (1000); ध्वज = सत्य; doEventLoop(); } पकड़ो (bad_alloc) {अगर (ध्वज) cout << "मेरे पास उपयोगकर्ता को संकेत देने के लिए उपयोग करने के लिए 4k है \ n"; } ' –

6

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

मेरा मानना ​​है कि यह किसी कार्रवाई के बीच में अपवादों को कम समझ में आता है, उपयोगकर्ता आमतौर पर ऑपरेशन को सफल या पूरी तरह विफल होने की अपेक्षा करता है।

9

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

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

+0

मैं आपके और एप्रामोग्राम दोनों को स्वीकार करना चाहता हूं, वे दोनों अच्छे जवाब प्रतीत होते हैं। चूंकि एप्रोग्रामर पहले था, मैं उसे स्वीकार कर रहा हूं। –

+0

yup yup। उनका भी अधिक विस्तृत है – jalf

0

हैंडल यह main() में (या क्यूटी में बराबर शीर्ष स्तर अपवाद संचालक)

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

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

3

यह एक अपेक्षाकृत पुराने धागा है, लेकिन यह ऊपर आया था जब मैं "std :: bad_alloc" विचार के लिए खोज रहा था, जब नए कर 2012

में यहाँ अधिभावी/हटाने मैं अवधारणा नहीं ले जाएगा "ओह अच्छी तरह से कुछ भी नहीं आप किसी भी तरह से "व्यवहार्य विकल्प के रूप में कर सकते हैं। मैं व्यक्तिगत रूप से उपरोक्त तरीके से "if (alloc()) {} else {error/handling}" तरीके से अपने आवंटन में उपयोग करता हूं। इस तरह से मैं उचित रूप से संभाल सकता हूं और, या प्रत्येक मामले को उनके अपने सार्थक संदर्भ में रिपोर्ट कर सकता हूं।

अब, कुछ अन्य संभावित समाधान हैं: 1) उस एप्लिकेशन के लिए नया/हटाएं जहां आप मेमोरी हैंडलिंग से अपना खुद का जोड़ सकते हैं।

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

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

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

2) पहले की तरह, वैश्विक "set_new_handler()" को अपने आप के हैंडलर के साथ पकड़ने के लिए सेट करें एक वैश्विक दायरे में स्मृति की स्थिति से बाहर। कम से कम # 1 में उल्लेखों के रूप में चीजों को संभाल सकता है।

1

वास्तविक प्रश्न reallty आपको std :: bad_alloc अपवादों को पकड़ना चाहिए? यदि आप स्मृति से बाहर निकलते हैं तो आप सबसे अधिक मामलों में वैसे भी बर्बाद हो जाते हैं और आपके प्रोग्राम को समाप्त करने पर विचार कर सकते हैं।

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