Catch(...) with unknown object - 我如何识别抛出的是什么?
Catch(...) with unknown object - how do I identify what was thrown?
我有一个我使用的库会抛出一些东西,但我不知道如何识别抛出的东西。
重现此代码的示例代码:
int main()
{
char* memoryOutOfBounds;
unsigned __int64 bigNumber = -1;
try {
throw std::string("Test");
memoryOutOfBounds = new char[bigNumber];
}
catch (const std::bad_alloc& ex)
{
printf("Exception: %s\n", ex.what());
}
catch (...)
{
printf("Unknown.\n");
}
return 0;
}
new char[bigNumber]
会抛出一个std::bad_alloc
,由std::exception
派生,会进入第一个分支。另外一个,throw std::string
会进入第二个分支。如何检查抛出的对象?我尝试使用 catch(void*)
希望捕获内存中的任何对象,但这并没有发生,那么我如何找出抛出的内容并从那里调试可能导致此问题的原因?
catch (...) {}
意思是:绝对接住所有抛出的东西并扔掉。这只是作为一种保障,所以没有例外会飞出 window 并摧毁整个房子。 (又名:应用程序因未处理的异常而终止)
无法判断这里扔了什么。
但是你知道 std::string 可以被抛出,你可以在
中捕捉到它
catch (const std::string& s) {}
块。每当您想捕获异常时,您确实需要知道抛出的是什么(类型)。
然而,大多数为异常添加自己的类型的库都会让它们继承自 std::exception。因此a
catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
}
块应该得到它们。
如果他们不继承自 std::exception and/or 阻止 what() 方法,这是使他们的库的使用变得更加困难的愚蠢方法。
但是,在库的文档中某处异常抛出行为应该被解释。
Edit :我认为 Boost Error Handling 文档中 "How should I design my exception classes" 下的第 1 点是每个库开发人员都应该牢记的。希望您的图书馆的开发人员确实牢记这一原则。 ;-)
确实没有标准的 C++ 方法来查询有关正在抛出的异常的任何信息。这很不幸,因为运行时具有该信息以匹配 catch
块。但是用户代码中无法访问该信息。
如果纯粹出于研究目的,例如因为您使用的库缺少文档而只是找出类型,您可以使用 std::current_exception()
获取一个 std::exception_ptr
对象,该对象存储(或引用)内部抛出的异常。此类型是 实现定义的,但您的调试器可能恰好为您提供了足够的信息。
#include <exception>
void foo()
{
try
{
function_that_throws();
}
catch(...)
{
std::exception_ptr p = std::current_exception();
// break here and inspect 'p' with a debugger
}
}
这个 Whosebug post 会很有帮助-
C++ get description of an exception caught in catch(...) block
从 C++11 开始,您可以使用指针捕获当前异常:
std::exception_ptr p; // default initialization is to nullptr
try {
throw std::string("Test");
}
catch(...)
{
p = std::current_exception();
}
我有一个我使用的库会抛出一些东西,但我不知道如何识别抛出的东西。
重现此代码的示例代码:
int main()
{
char* memoryOutOfBounds;
unsigned __int64 bigNumber = -1;
try {
throw std::string("Test");
memoryOutOfBounds = new char[bigNumber];
}
catch (const std::bad_alloc& ex)
{
printf("Exception: %s\n", ex.what());
}
catch (...)
{
printf("Unknown.\n");
}
return 0;
}
new char[bigNumber]
会抛出一个std::bad_alloc
,由std::exception
派生,会进入第一个分支。另外一个,throw std::string
会进入第二个分支。如何检查抛出的对象?我尝试使用 catch(void*)
希望捕获内存中的任何对象,但这并没有发生,那么我如何找出抛出的内容并从那里调试可能导致此问题的原因?
catch (...) {}
意思是:绝对接住所有抛出的东西并扔掉。这只是作为一种保障,所以没有例外会飞出 window 并摧毁整个房子。 (又名:应用程序因未处理的异常而终止)
无法判断这里扔了什么。
但是你知道 std::string 可以被抛出,你可以在
中捕捉到它catch (const std::string& s) {}
块。每当您想捕获异常时,您确实需要知道抛出的是什么(类型)。
然而,大多数为异常添加自己的类型的库都会让它们继承自 std::exception。因此a
catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
}
块应该得到它们。
如果他们不继承自 std::exception and/or 阻止 what() 方法,这是使他们的库的使用变得更加困难的愚蠢方法。
但是,在库的文档中某处异常抛出行为应该被解释。
Edit :我认为 Boost Error Handling 文档中 "How should I design my exception classes" 下的第 1 点是每个库开发人员都应该牢记的。希望您的图书馆的开发人员确实牢记这一原则。 ;-)
确实没有标准的 C++ 方法来查询有关正在抛出的异常的任何信息。这很不幸,因为运行时具有该信息以匹配 catch
块。但是用户代码中无法访问该信息。
如果纯粹出于研究目的,例如因为您使用的库缺少文档而只是找出类型,您可以使用 std::current_exception()
获取一个 std::exception_ptr
对象,该对象存储(或引用)内部抛出的异常。此类型是 实现定义的,但您的调试器可能恰好为您提供了足够的信息。
#include <exception>
void foo()
{
try
{
function_that_throws();
}
catch(...)
{
std::exception_ptr p = std::current_exception();
// break here and inspect 'p' with a debugger
}
}
这个 Whosebug post 会很有帮助- C++ get description of an exception caught in catch(...) block
从 C++11 开始,您可以使用指针捕获当前异常:
std::exception_ptr p; // default initialization is to nullptr
try {
throw std::string("Test");
}
catch(...)
{
p = std::current_exception();
}