问题
Say I have:
try
{
externalLibrary::doSomething();
}
catch (std::exception &e)
{
//yay I know what to do
}
catch (...)
{
//darn, I've no idea what happened!
}
There might be cases you get an exception and you don't know where it's coming from or why - in some external library with no debug info. Is there a way to find what was thrown, or otherwise obtain any data associated with it? They might be doing:
throw myStupidCustomString("here is some really useful information");
But I'd never know if I catch ...
Working in MSVC++ 2008 if it matters.
回答1:
Because C++ is statically typed, you must catch a known type. However, you can call an external function (or set of functions) which handle exception types unknown at the point you call them. If these handlers all have known types, you can register them to be dynamically tried.
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.
}
}
}
Finally, if you know implementation specifics, you can use those to extract whatever additional information your implementation exposes. C++0x exposes some specifics in a portable way, too; look at std::exception_ptr.
回答2:
If you use gcc or CLANG you can use a trick to know the 'unknown' exception type. Keep in mind that this is NON-standard !
#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);
}
回答3:
There's no way to know the type of the exception in C++ (in catch(...)
block, I mean, of cource)
You could just hope that you know what exactly externalLibrary::doSomething();
does, if you have written it, or, as in your case, you could just hope, that there's really nice documentation for externalLibrary::doSomething();
and read it, if there's such. All good libraries have detailed documentation.
回答4:
You can't in standard C++. I would consider such exceptions to be very exceptional, and handle them by trying to log the fact that you had a bad exception, and then try to quit the program, while you still can.
If you're lucky, you may be able to save any data.
来源:https://stackoverflow.com/questions/4885334/c-finding-the-type-of-a-caught-default-exception