C++ - 查找捕获的默认异常的类型

Mr.*_*Boy 11 c++ exception-handling visual-studio-2008

说我有:

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

在某些没有调试信息的外部库中,可能会出现异常并且您不知道它来自何处或原因的情况.有没有办法找到抛出的内容,或以其他方式获取与之相关的任何数据?他们可能会这样做:

throw myStupidCustomString("here is some really useful information");
Run Code Online (Sandbox Code Playgroud)

但我永远不会知道我是否抓住了 ...

如果重要的话,在MSVC++ 2008中工作.

Grz*_*zak 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);
}
Run Code Online (Sandbox Code Playgroud)


Fre*_*urk 6

因为C++是静态类型的,所以必须捕获已知类型.但是,您可以调用外部函数(或函数集)来处理在调用它们时未知的异常类型.如果这些处理程序都具有已知类型,则可以将它们注册为动态尝试.

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.
  }
}
Run Code Online (Sandbox Code Playgroud)

用途:

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;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

处理链:

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.
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

最后,如果您了解实现细节,则可以使用它们来提取实现所暴露的任何其他信息.C++ 0x也以可移植的方式公开了一些细节; 看看std :: exception_ptr.