2011-02-03 3 views
10

의 유형을 찾아 내가 가진 말 디버그 정보가 없습니다. 무엇이 던져 졌는지 찾아내는 방법이 있습니까? 그렇지 않으면 관련된 데이터를 얻는 방법이 있습니까?C++ 잡힌 기본 예외

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

하지만 ++ 2008이 중요한 경우 MSVC에서 작업

...을 잡으면 나는 결코 알지 못할 것입니다 : 그들은 일을 할 수 .

답변

6

C++은 정적으로 입력되므로 알려진 유형을 catch해야합니다. 그러나 호출 한 지점에서 알 수없는 예외 유형을 처리하는 외부 함수 (또는 함수 집합)를 호출 할 수 있습니다. 이러한 핸들러에 알려진 유형이 모두있는 경우이를 동적으로 시도하도록 등록 할 수 있습니다.

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. 
    } 
    } 
} 

마지막으로, 당신은 당신의 구현을 노출하는 추가 정보를 추출하는 사람들을 사용할 수 있습니다. C++ 0x는 몇 가지 세부 사항을 이식성있는 방식으로 노출합니다. std :: exception_ptr을 보라.

+0

안녕하세요, 저는 이것이 훌륭한 대답이라고 생각합니다.그러나이 표준 작동 여부에 대한 표준 정보는 찾을 수 없습니다. 나는 그것을 테스트했고 VisualStudio, GCC 및 LLVM에서 모두 작동하지만 완전히 이유는 모르겠습니다. 그래서 새로운'try {} catch() {}'블록을 입력해도 어떤 식 으로든 현재의 예외에는 영향을 미치지 않습니까? 감사! – NHDaly

+0

왜 작동하지 않을지 잘 모르겠다 고 생각합니다. try 블록을 사용하면 현재 예외에는 영향을주지 않지만 두 번 확인하고 싶을 것입니다. – NHDaly

1

표준 C++에서는 사용할 수 없습니다. 이러한 예외는 매우 예외적 인 것으로 간주하고 나쁜 예외가 있다는 사실을 기록하여 처리 한 다음 프로그램을 종료하려고 시도하지만 여전히 할 수 있습니다.

운이 좋다면 모든 데이터를 저장할 수 있습니다.

2

당신은 당신이 알고있는 희망 단지 수 (catch(...) 블록에, 나는 cource의 의미) C++의 예외의 종류를 알 수있는 방법이 없습니다 정확히 externalLibrary::doSomething(); 당신이 그것을 작성한 경우, 수행, 또는 귀하의 경우처럼, 당신은 단지 externalLibrary::doSomething();에 대한 훌륭한 문서가 있다는 것을 희망 할 수 있습니다. 모든 훌륭한 라이브러리에는 상세한 문서가 있습니다.

+0

예외에 대한 자세한 내용은 필자의 경험에 비추어 볼 때 매개 변수에 대한 일반적인 문서가 아닙니다. 그렇다면 표준 가능성을 테스트해야 할 것입니다 ... 시스템 예외는 무엇입니까? –

+0

"시스템 예외는 무엇입니까?" 그들이 C++ 프로그램에서 잡힐 수 있는지 나는 모른다 :? 또한, 내가 사용한 라이브러리의 대부분은 문서화 된 자체적 인 예외 계층 구조를 가지고 있습니다. 그러나 물론 이것은 모든 도서관에 그런 것이 있다는 것을 의미하지는 않습니다. 또한 C lib 인 경우 예외가 발생하지 않습니다. –

+0

나는 null-ptr 액세스, div/0 등과 같은 것들을 잡는 특별한 방법이 없다는 것을 의미합니까? 제 3 자 lib가 버그가있는 그런 문제를 잡을 방법이 있다고 생각했습니다. –

15

gcc 또는 CLANG를 사용하면 트릭을 사용하여 '알 수없는'예외 유형을 알 수 있습니다. 이것이 비표준임을 명심하십시오!

#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

Omg. 나는 너에게 지금 키스 할 수있어. 감사합니다 <3 –