2011-02-03 22 views
10

के प्रकार खोजने कहो मेरे पास है:सी ++ - एक पकड़ा डिफ़ॉल्ट अपवाद

try 
{ 
externalLibrary::doSomething(); 
} 
catch (std::exception &e) 
{ 
//yay I know what to do 
} 
catch (...) 
{ 
//darn, I've no idea what happened! 
} 

मामलों आप एक अपवाद प्राप्त हो सकती है और आप नहीं जानते कि कहाँ से आ रहा है या क्यों है - साथ कुछ बाहरी पुस्तकालय में कोई डीबग जानकारी नहीं। क्या फेंक दिया गया खोजने का कोई तरीका है, या अन्यथा इसके साथ जुड़े किसी भी डेटा को प्राप्त करें? वे कर किया जा सकता है:

throw myStupidCustomString("here is some really useful information"); 

लेकिन मैं कभी पता नहीं अगर मैं ...

पकड़ने MSVC++ 2008 अगर यह मायने रखती में कार्य करना चाहते हैं।

उत्तर

6

क्योंकि सी ++ स्थिर रूप से टाइप किया गया है, तो आपको एक ज्ञात प्रकार को पकड़ना होगा। हालांकि, आप बाहरी फ़ंक्शन (या फ़ंक्शंस सेट) को कॉल कर सकते हैं जो उस बिंदु पर अज्ञात अपवाद प्रकारों को संभालता है जिन्हें आप कॉल करते हैं। यदि इन हैंडलर सभी को ज्ञात प्रकार हैं, तो आप गतिशील रूप से प्रयास करने के लिए उन्हें पंजीकृत कर सकते हैं।

struct myStupidCustomString { 
    myStupidCustomString(char const *what) : what (what) {} 
    char const *what; 
}; 

void throws() { 
    throw myStupidCustomString("here is some really useful information"); 
} 

// The external library can provide a function, or you can provide a wrapper, which 
// extracts information from "unknown" exception types. 
std::string extract_from_unknown_external_exception() { 
    try { throw; } 
    catch (myStupidCustomString &e) { 
    return e.what; 
    } 
    catch (...) { 
    throw; // Rethrow original exception. 
    } 
} 

Use:

void example() { 
    try { throws(); } 
    catch (...) { 
    try { 
     std::string extracted = extract_from_unknown_external_exception(); 
     std::cout << "extracted: " << extracted << '\n'; 
    } 
    catch (...) { 
     // Chain handlers for other types; e.g. exception types from other libraries. 
     // Or do something generic for the unknown exception. 

     // Or rethrow the original unknown exception: 
     throw; 
    } 
    } 
} 

Handler chain:

typedef std::string Extract(); 
std::vector<Extract*> chain (1, &extract_from_unknown_external_exception); 
// Chain would normally be initialized using whatever scheme you prefer for 
// initializing global objects. 
// A list or other container (including a manual linked list that doesn't 
// require dynamic allocation) may be more appropriate, depending on how you 
// want to register and unregister handlers. 
std::string process_chain() { 
    for (std::vector<Extract*>::iterator x = chain.begin(); x != chain.end(); ++x) { 
    try { 
     return (*x)(); 
    } 
    catch (...) {} // That handler couldn't handle it. Proceed to next. 
    } 
    throw; // None could handle it, rethrow original exception. 
} 

void example() { 
    try { throws(); } 
    catch (...) { 
    try { 
     std::string extracted = process_chain(); 
     std::cout << "extracted: " << extracted << '\n'; 
    } 
    catch (...) { 
     throw; // Rethrow unknown exception, or otherwise handle it. 
    } 
    } 
} 

अंत में, यदि आप कार्यान्वयन बारीकियों पता है, तुम उन को निकालने के लिए अपने कार्यान्वयन को उजागर करता है जो कुछ अतिरिक्त जानकारी का उपयोग कर सकते हैं। सी ++ 0 एक्स कुछ पोर्टेबल तरीके से कुछ विनिर्देशों का खुलासा करता है; std :: upgrade_ptr पर देखें।

+0

हाय, मुझे लगता है कि यह एक अच्छा जवाब है।हालांकि, मुझे इस मानक के बारे में मानक में कोई जानकारी नहीं मिल रही है कि यह मानक व्यवहार है या नहीं। मैंने इसका परीक्षण किया है, और यह विजुअलस्टूडियो, जीसीसी और एलएलवीएम दोनों में काम करता है, लेकिन मुझे पूरा यकीन नहीं है कि क्यों। तो एक नया 'प्रयास {} पकड़() {} 'ब्लॉक दर्ज करना वर्तमान अपवाद को किसी भी तरह से प्रभावित नहीं करता है? धन्यवाद! – NHDaly

+0

मुझे लगता है कि मुझे यह भी यकीन नहीं है कि यह क्यों काम नहीं करेगा .. ऐसा लगता है कि एक कोशिश ब्लॉक में प्रवेश करने से कोई मौजूदा अपवाद प्रभावित नहीं होगा, लेकिन मुझे लगता है कि मैं सिर्फ दो बार जांच करना चाहता हूं। – NHDaly

1

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

यदि आप भाग्यशाली हैं, तो आप किसी भी डेटा को सहेजने में सक्षम हो सकते हैं।

2

कोई रास्ता नहीं सी में अपवाद के प्रकार पता करने के लिए ++ (catch(...) ब्लॉक में, मैं cource की मतलब है,)

तुम बस आशा है कि हो सकता है कि आप जानते हैं कि नहीं है वास्तव में क्या externalLibrary::doSomething();, करता है अगर आप इसे लिखा है, या , जैसा कि आपके मामले में, आप उम्मीद कर सकते हैं कि externalLibrary::doSomething(); के लिए वास्तव में अच्छा प्रलेखन है और यदि ऐसा है, तो इसे पढ़ें। सभी अच्छी पुस्तकालयों में विस्तृत दस्तावेज हैं।

+0

अपवादों का विस्तृत दस्तावेज मेरे अनुभव में पैराम के सभ्य दस्तावेज के समान सामान्य नहीं है। लेकिन अगर ऐसा है, तो मुझे मानक संभावनाओं का परीक्षण करना होगा ... सिस्टम अपवादों के बारे में क्या? –

+0

"सिस्टम अपवादों के बारे में क्या है" से आपका क्या मतलब है? मुझे नहीं पता कि उन्हें सी ++ कार्यक्रम में पकड़ा जा सकता है:? साथ ही, मैंने उपयोग की जाने वाली अधिकांश पुस्तकालयों में अपना स्वयं का अपवाद पदानुक्रम है जो अच्छी तरह से प्रलेखित है। लेकिन, ज़ाहिर है, इसका मतलब यह नहीं है कि सभी पुस्तकालयों में ऐसी चीज है। इसके अलावा, अगर यह सी lib है, तो आप जानते हैं कि कोई अपवाद नहीं फेंक दिया जाता है। –

+0

मेरा मतलब था, क्या नल-पीआरटी एक्सेस, div/0 जैसी चीजों को पकड़ने के लिए विशेष तरीके नहीं हैं? मैंने सोचा कि ऐसी समस्याओं को पकड़ने के तरीके थे जहां तीसरे पक्ष की मुक्ति छोटी है? –

15

यदि आप जीसीसी या क्लैंग का उपयोग करते हैं तो आप 'अज्ञात' अपवाद प्रकार को जानने के लिए एक चाल का उपयोग कर सकते हैं। ध्यान रखें कि यह गैर मानक है!

#include <cstdlib> 
#include <iostream> 
#include <cxxabi.h> 


using namespace __cxxabiv1; 

std::string util_demangle(std::string to_demangle) 
{ 
    int status = 0; 
    char * buff = __cxxabiv1::__cxa_demangle(to_demangle.c_str(), NULL, NULL, &status); 
    std::string demangled = buff; 
    std::free(buff); 
    return demangled; 
} 

struct MyCustomClass 
{}; 

int main(int argc, char * argv[]) 
{ 
    try 
    { 
     throw MyCustomClass(); 
    } 
    catch(...) 
    { 
     std::cout << "\nUnknown exception type: '" << util_demangle(__cxa_current_exception_type()->name()) << "'" << std::endl; 
    } 
    return(0); 
} 
+0

ओएमजी। मैं अभी आपको चुंबन दे सकता हूं। धन्यवाद <3 –

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