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

时间:2011-02-03 11:04:49

标签: c++ visual-studio-2008 exception-handling

说我有:

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。

4 个答案:

答案 0 :(得分: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);
}

答案 1 :(得分: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.
  }
}

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。

答案 2 :(得分:2)

无法知道C ++中的异常类型(在catch(...)块中,我的意思是cource)

你可能希望你知道externalLibrary::doSomething();究竟是做什么的,如果你已经写好了,或者,就你的情况而言,你可能只是希望,externalLibrary::doSomething();有非常好的文档和阅读它,如果有的话。所有好的图书馆都有详细的文档。

答案 3 :(得分:1)

你不能在标准C ++中。我会认为这些异常是非常特殊的,并通过尝试记录您有一个错误异常的事实处理它们,然后尝试退出程序,而您仍然可以。

如果幸运的话,您可以保存任何数据。