簡體   English   中英

C ++ - 查找捕獲的默認異常的類型

[英]C++ - finding the type of a caught default exception

說我有:

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中工作。

如果您使用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);
}

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

用途

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

處理鏈

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。

沒有辦法知道C ++中的異常類型(在catch(...)塊中,我的意思是,cource)

你可以希望你知道究竟是什么externalLibrary::doSomething(); 是的,如果你已經寫過,或者,就像你的情況一樣,你可以希望,對於externalLibrary::doSomething();有非常好的文檔externalLibrary::doSomething(); 並閱讀它,如果有的話。 所有好的庫都有詳細的文檔。

你不能在標准的C ++中。 我會認為這些異常非常特殊,並通過嘗試記錄您有一個錯誤異常的事實來處理它們,然后嘗試退出程序,而您仍然可以。

如果幸運的話,您可以保存任何數據。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM