2008-11-09 13 views
18

क्या अपवादों को पकड़ने का कोई तरीका है जो अन्यथा अनचाहे हैं (कैच ब्लॉक के बाहर फेंकने सहित)?सभी अनचाहे सी ++ अपवादों को पकड़ना?

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

कुछ की तरह:

global_catch() 
{ 
    MessageBox(NULL,L"Fatal Error", L"A fatal error has occured. Sorry for any inconvience", MB_ICONERROR); 
    exit(-1); 
} 
global_catch(Exception *except) 
{ 
    MessageBox(NULL,L"Fatal Error", except->ToString(), MB_ICONERROR); 
    exit(-1); 
} 

उत्तर

21

इस पकड़ने के लिए, अप्रत्याशित अपवाद इस्तेमाल किया जा सकता।

एक कोशिश पकड़ ब्लॉक के बिना, मुझे नहीं लगता कि आप अपवाद पकड़ कर सकते हैं, तो अपने कार्यक्रम की संरचना है, तो अपवाद कोड thowing आज़माएं/कैच के नियंत्रण में है।

+0

बात मैं वास्तव में न एक बड़ा "सुपर कोशिश" ब्लॉक में अपने पूरे एप्लिकेशन को रखना चाहता हूँ ... के बाद से प्रदर्शन थोड़े महत्वपूर्ण है ... मैं जानता हूँ कि कुछ theres है कहीं और क्योंकि उदाहरण के लिए दृश्य स्टूडियो पता लगा सकता है/पकड़ सकता है/जो कुछ भी छोड़कर और तोड़ने और डीबग करने की पेशकश करता है। –

+0

सुपर कोशिश ब्लॉक काम करता है। आप मुख्य में एक बार इसे स्थापित करने की लागत का भुगतान करते हैं। एक बार एक प्रदर्शन मुद्दा नहीं है। – EvilTeach

+0

बस एक बार? मुझे यकीन है कि एक बार कोशिश करने के बाद ब्लॉक ने फेंकने के बाद सफाई के लिए कुछ प्रकार के "ट्रेस" को बनाए रखा, जिससे ब्लॉक की सामग्री के आधार पर लागत कम हो गई? –

4

यह जो मैं हमेशा मुख्य में क्या()

int main() 
{ 
    try 
    { 
     // Do Work 
    } 
    catch(std::exception const& e) 
    { 
     Log(e.what()); 
     // If you are feeling mad (not in main) you could rethrow! 
    } 
    catch(...) 
    { 
     Log("UNKNOWN EXCEPTION"); 
     // If you are feeling mad (not in main) you could rethrow! 
    } 
} 
+1

यह जाने का एक अच्छा तरीका है, लेकिन किसी को यह ध्यान में रखना चाहिए कि इससे संभव स्थिर इनिट अपवाद (मुझे विश्वास है) नहीं मिलेगा। – kralyk

+0

@kralyk: स्थैतिक भंडारण अवधि वस्तुओं के रचनाकारों/विनाशकों में उत्पन्न अपवादों को पकड़ने का कोई तरीका नहीं है। इन मामलों में 'std :: terminate()' कहा जाता है। –

+1

मुझे पता है ... तकनीकी रूप से, set_terminate() (मेरा उत्तर देखें) का उपयोग करके यह संभव हो सकता है, लेकिन स्थिर इनिट ऑर्डर कार्यान्वयन-परिभाषित है, इसलिए इसकी कोई गारंटी नहीं है ... – kralyk

9

आप Windows पर SetUnhandledExceptionFilter उपयोग कर सकते हैं, जो सभी बिना क्रिया SEH अपवाद पकड़ेगा है।

आम तौर पर यह आपकी सभी समस्याओं के लिए पर्याप्त होगा क्योंकि आईआईआरसी सभी सी ++ अपवाद एसईएच के रूप में लागू किए जाते हैं।

8

किसी भी पकड़ ब्लॉक के बिना, आपको कोई अपवाद नहीं मिलेगा। आप अपने मुख्य() (और प्रत्येक अतिरिक्त थ्रेड में इसके बराबर) में एक पकड़ (...) ब्लॉक कर सकते हैं। इस पकड़ ब्लॉक में आप अपवाद विवरण पुनर्प्राप्त कर सकते हैं और आप लॉगिंग और बाहर निकलने जैसे उनके बारे में कुछ कर सकते हैं।

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

विंडोज़ पर, कोई कोर फ़ाइलें नहीं हैं, इसलिए मैं पकड़ (...) ब्लॉक रखने का सुझाव दूंगा। कि ब्लॉक से, आप आमतौर पर वास्तविक अपवाद फिर से शुरू करने के लिए एक समारोह कहेंगे:

std::string ResurrectException() 
    try { 
     throw; 
    } catch (const std::exception& e) { 
     return e.what(); 
    } catch (your_custom_exception_type& e) { 
     return e.ToString(); 
    } catch(...) { 
     return "Ünknown exception!"; 
    } 
} 


int main() { 
    try { 
     // your code here 
    } catch(...) { 
     std::string message = ResurrectException(); 
     std::cerr << "Fatal exception: " << message << "\n"; 
    } 
} 
+2

विंडोज़ में .dmp फ़ाइलें हैं, जो मोटे तौर पर हैं मूल फ़ाइलों के बराबर, लेकिन वे उपयोगकर्ता त्रुटि रिपोर्टिंग वेबसाइट पर अपलोड हो जाते हैं (यदि उपयोगकर्ता उपयोगकर्ता की हार्ड ड्राइव को कूड़ेदान के बजाय "भेज" पर क्लिक करता है। साथ ही, यदि आपके पास एक इन-टाइम-टाइम डीबगर कॉन्फ़िगर किया गया है, तो विंडोज इसके बजाय डीबगर में टूट जाएगा। – bk1e

+1

std :: स्ट्रिंग का निर्माता स्वयं को अपवाद फेंक सकता है। और इसलिए std: cerr के लिए मुद्रण करता है। फिर फिर आप भाग्यशाली 99% भाग्यशाली हो सकते हैं। – rxantos

7

अद्यतन: यह C++ 98 केवल शामिल किया गया।

मेयर (पीजी 76) द्वारा More Effective C++ से, आप एक फ़ंक्शन को परिभाषित कर सकते हैं जिसे फ़ंक्शन कहा जाता है जब कोई अपवाद अपवाद उत्पन्न करता है जिसे इसके अपवाद विनिर्देश द्वारा परिभाषित नहीं किया जाता है।

void convertUnexpected() 
{ 
    // You could redefine the exception here into a known exception 
    // throw UnexpectedException(); 

    // ... or I suppose you could log an error and exit. 
} 

अपने आवेदन में समारोह रजिस्टर:

std::set_unexpected(convertUnexpected); 

अगर एक समारोह के लिए एक अपवाद है कि इसके अपवाद विनिर्देश ... जो यह केवल इसका मतलब है द्वारा परिभाषित नहीं उत्पन्न करता है आपका समारोह convertUnexpected() कहा जाता हो जाएगा यदि आप अपवाद विनिर्देशों का उपयोग कर रहे हैं तो काम करता है। ; (

+3

मुझे पता है कि यह उत्तर सी ++ 11 मानक उपलब्ध होने से बहुत पहले किया गया था, लेकिन वर्तमान में 'std :: set_unexpected' को बहिष्कृत किया गया है। – scrutari

1

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

19

चेक बाहर std::set_terminate()

+0

क्या आप 'terminate_handler' में अपवाद का उपयोग कर सकते हैं? –

+0

@ KonstantinA.Magg मुझे ऐसा नहीं लगता है। चूंकि अपवाद _any_ प्रकार का हो सकता है, इसलिए इसका उपयोग करने का कोई तरीका नहीं है ... – kralyk

+1

हाँ आप std :: uncaugth_exception() और std :: current_exception {) –

3

बशर्ते कि सी ++ 11 उपलब्ध है, इस दृष्टिकोण हो सकता है इस्तेमाल किया जा (से उदाहरण देखें: http://en.cppreference.com/w/cpp/error/rethrow_exception): इस

unexpected exception: wrong input parameters 
Aborted 
की तरह कुछ है करने के लिए:

#include <iostream> 
#include <exception> 

void onterminate() { 
    try { 
    auto unknown = std::current_exception(); 
    if (unknown) { 
     std::rethrow_exception(unknown); 
    } else { 
     std::cerr << "normal termination" << std::endl; 
    } 
    } catch (const std::exception& e) { // for proper `std::` exceptions 
    std::cerr << "unexpected exception: " << e.what() << std::endl; 
    } catch (...) { // last resort for things like `throw 1;` 
    std::cerr << "unknown exception" << std::endl; 
    } 
} 

int main() { 
    std::set_terminate(onterminate); // set custom terminate handler 
    // code which may throw... 
    return 0; 
} 

यह दृष्टिकोण भी आप बिना क्रिया अपवाद के लिए सांत्वना उत्पादन अनुकूलित करने के लिए अनुमति देता हैबजाय इस बात का

:

terminate called after throwing an instance of 'std::logic_error' 
    what(): wrong input parameters 
Aborted 
संबंधित मुद्दे