说我有:
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。
答案 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;
}
}
}
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 ++中。我会认为这些异常是非常特殊的,并通过尝试记录您有一个错误异常的事实处理它们,然后尝试退出程序,而您仍然可以。
如果幸运的话,您可以保存任何数据。