2014-10-03 10 views
6

मेरे पास एक बहुत ही विस्तार से लॉगिंग कार्यक्षमता के साथ (विजुअल) सी ++ में लिखी गई एक विंडोज सेवा है जिसने अक्सर मुझे कभी-कभी त्रुटियों का कारण खोजने में मदद की है। असल में मैं प्रत्येक वापसी मूल्य की जांच करता हूं और लॉग ऑन करता हूं कि कहां चल रहा है और कहां से त्रुटियां आ रही हैं।सी ++: क्या मुझे सभी अपवादों को पकड़ना चाहिए या प्रोग्राम को क्रैश करना चाहिए?

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

मेरे पास आज एक सामान्य पकड़ है-जो सब कुछ पकड़ता है और प्रोग्राम को बंद करने से पहले एक त्रुटि लॉग करता है। यह उपयोगकर्ता के दृष्टिकोण से अच्छा है - ऐप क्रैश के बजाय क्लीन शट डाउन - लेकिन मेरे लिए बुरा है क्योंकि मुझे केवल अपवाद से एक सामान्य संदेश मिलता है (उदा। "श्रेणी से बाहर सरणी") लेकिन यह नहीं पता कि वह कहां से आ रहा है।

कैच-सब को हटाने और प्रोग्राम को क्रैश करने के बजाय बेहतर नहीं होगा? मैं ग्राहक को विंडोज़ को एप्लिकेशन क्रैश डंप बनाने के लिए निर्देशित कर सकता हूं (जैसा कि here वर्णित है)। डंप फ़ाइल के साथ WinDbg मुझे उस कोड की स्थिति में बिल्कुल इंगित करेगा जहां अपवाद फेंक दिया गया था।

+1

यदि ग्राहक अप्रत्याशित रूप से दुर्घटनाग्रस्त हो जाता है, तो ग्राहक के लिए यह अच्छा नहीं है। यह बेहतर है अगर यह कभी भी दुर्घटनाग्रस्त नहीं होता है। और, पकड़ो (...) ऊपर बताए अनुसार एक दुःस्वप्न डीबगिंग करता है। शुरुआत में यह मुश्किल हो सकता है कि ग्राहकों को मुश्किल दुर्घटना हो, लेकिन जैसा कि रिपोर्ट किया जाता है, वे कम से कम लगातार (सिद्धांत में) बन जाएंगे, जब तक यह 0 तक पहुंच न जाए। – RPGillespie

+0

@ आरपीजीलेस्पी: धन्यवाद, यह मेरी तर्क कम या ज्यादा है, भी। यदि मुझे गलत क्रैश नहीं हैं तो मैं कोड के उन क्षेत्रों को ढूंढ और ठीक कर सकता हूं जहां अपवादों को फेंक दिया जा सकता है। –

+0

शून्य त्रुटि से विभाजित करने के लिए कोई बहाना नहीं है या किसी भी लिखित सी ++ प्रोग्राम में कभी भी उठाए गए अन्य तर्क त्रुटि का कोई बहाना नहीं है। यह मैला प्रोग्राम डिजाइन का संकेतक है। –

उत्तर

4

आप AddVectoredExceptionHandler पर कॉल करके एक कस्टम, वेक्टर अपवाद हैंडलर पंजीकृत कर सकते हैं।

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

ऐसा करने के लिए कोड लिखना पूरी तरह से मामूली नहीं है बल्कि रॉकेट सर्जरी नहीं है।

मैंने व्यक्तिगत रूप से इसे सी ++ में व्यक्तिगत रूप से नहीं किया है, लेकिन अगर मैं तैयार-निर्मित पुस्तकालय नहीं था, तो यह आश्चर्यचकित होगा कि यह कहीं भी उपलब्ध है, अगर आपके पास समय या झुकाव नहीं है ।

+0

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

+0

मुझे दस्तावेज को पर्याप्त रूप से मिला जो मुझे करने की ज़रूरत थी। इसके बारे में विशिष्ट प्रश्न पूछने के लिए स्वतंत्र महसूस करें, यदि आपके पास है, तो कोई और मैं (या कोई और) मदद करने की कोशिश करेगा। –

0

जहां त्रुटि हुई थी और आप विवरण के साथ अपवाद फेंक कर सकते हैं क्यों:

throw std::string("could not open this file"); 

आप आप मानक मैक्रो _ _ फ़ाइल का उपयोग कर सकते हर संभव त्रुटि के लिए अलग अलग वर्णन लिखना नहीं चाहते, तो _ _ और _ _ लाइन _ _:

#define _MyError std::string("error in " __FILE__ + std::to_string(__LINE__)) 
// ... 
throw _MyError; 

हैं स्रोत फ़ाइल नाम और त्रुटि की रेखा पर्याप्त नहीं है और आपको अधिक जानकारी की आवश्यकता है, उदाहरण के लिए स्टैक ट्रेस या मेमोरी मान, आपका प्रोग्राम डीबग रिपोर्ट उत्पन्न कर सकता है। Google ब्रेकपैड एक सी ++ लाइब्रेरी है जो आपको पोर्टेबल तरीके से ऐसा करने की अनुमति देती है। WxWidgets लाइब्रेरी से क्लास wxDebugReport एक विकल्प है। विंडोज़ पर डीबग रिपोर्ट में एक मिनीडम्प फ़ाइल शामिल हो सकती है जिसे विजुअल स्टूडियो में लोड किया जा सकता है और आपको डीबगिंग के समान त्रुटि का विश्लेषण करने की अनुमति देता है।

+0

कृपया सुनिश्चित करें कि जो कुछ भी आप फेंकते हैं वह 'std :: runtime_error' या' std :: logic_error' से लिया गया है। अंततः 'std :: अपवाद' से प्राप्त वस्तुओं को फेंकने से आप C++ 11 '' हेडर में रखे गए सभी अच्छे कामों को पूर्ववत कर देते हैं। –

0

कैच-सब को हटाने और प्रोग्राम को क्रैश करने के बजाय बेहतर नहीं होगा?

आप बाकी-सब कर सकते हैं और

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

यदि आप ऐसा कुछ नहीं करते हैं, तो आप कैच-सब को भी हटा सकते हैं।

पठनीयता और व्यावहारिकता के कारणों के लिए मैं अलग-अलग प्रयास/पकड़ ब्लॉक में कोड की हर कुछ पंक्तियों को लपेटना नहीं चाहता हूं।

और फिर भी यदि आप चाहते हैं कि आपका प्रोग्राम पुनर्प्राप्त करने में सक्षम हो, तो यह वही है जो आपको करना है। आप क्या कर सकते हैं

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

बिंदु यह है कि आपका प्रोग्राम वैध स्थिति में वापस आ सकता है।

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