C ++ – recherche du type d’une exception par défaut interceptée

Dis que j’ai:

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

Il peut y avoir des cas où vous obtenez une exception et vous ne savez pas d’où elle vient ni pourquoi – dans une bibliothèque externe sans informations de débogage. Existe-t-il un moyen de rechercher ce qui a été jeté ou d’obtenir des données associées? Ils pourraient faire:

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

Mais je ne saurais jamais si j’attrape ...

Travailler dans MSVC ++ 2008 si cela compte.

C ++ étant typé de manière statique, vous devez capturer un type connu. Cependant, vous pouvez appeler une fonction externe (ou un ensemble de fonctions) qui gèrent des types d’exception inconnus au point où vous les appelez. Si ces gestionnaires ont tous des types connus, vous pouvez les enregistrer pour qu’ils soient testés de manière dynamic.

 struct myStupidCustomSsortingng { myStupidCustomSsortingng(char const *what) : what (what) {} char const *what; }; void throws() { throw myStupidCustomSsortingng("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::ssortingng extract_from_unknown_external_exception() { try { throw; } catch (myStupidCustomSsortingng &e) { return e.what; } catch (...) { throw; // Rethrow original exception. } } 

Utiliser :

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

Chaîne de manutention :

 typedef std::ssortingng Extract(); std::vector 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::ssortingng process_chain() { for (std::vector::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::ssortingng extracted = process_chain(); std::cout << "extracted: " << extracted << '\n'; } catch (...) { throw; // Rethrow unknown exception, or otherwise handle it. } } } 

Enfin, si vous connaissez les spécificités de l'implémentation, vous pouvez les utiliser pour extraire toutes les informations supplémentaires exposées par votre implémentation. C ++ 0x expose également certains détails de manière portable; Regardez std :: exception_ptr.

Si vous utilisez gcc ou CLANG, vous pouvez utiliser une astuce pour connaître le type d’exception «inconnu». Gardez à l’esprit que c’est non standard!

 #include  #include  #include  using namespace __cxxabiv1; std::ssortingng util_demangle(std::ssortingng to_demangle) { int status = 0; char * buff = __cxxabiv1::__cxa_demangle(to_demangle.c_str(), NULL, NULL, &status); std::ssortingng 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); } 

Il n’y a aucun moyen de connaître le type de l’exception en C ++ (dans le bloc catch(...) , je veux dire, bien sûr)

Vous pouvez simplement espérer savoir exactement ce que externalLibrary::doSomething(); fait, si vous l’avez écrit, ou, comme dans votre cas, vous pouvez simplement espérer qu’il existe une très bonne documentation pour externalLibrary::doSomething(); et le lire, s’il y en a un. Toutes les bonnes bibliothèques ont une documentation détaillée.

Vous ne pouvez pas en C ++ standard. Je considérerais ces exceptions comme très exceptionnelles et les gérerais en essayant de consigner le fait que vous aviez une mauvaise exception, puis d’essayer de quitter le programme pendant que vous le pouvez toujours.

Si vous avez de la chance, vous pourrez peut-être sauvegarder des données.