我有一个通过现有代码使用的错误记录功能。如果可能的话,我想通过检测何时从catch
块中调用它来从异常中提取其他信息来改进它。在catch
块中,您可以重新抛出异常并在本地捕获它。
void log_error()
{
try {
throw; // Will rethrow the exception currently being caught
}
catch (const std::exception & err) {
// The exception's message can be obtained
err.what();
}
}
如果您不在
catch
块的上下文中,则此函数将调用std::terminate
。我正在寻找一种检测是否存在要抛出的异常的方法,调用throw;
是否安全?我已经找到了 std::uncaught_exception
,但它似乎仅适用于抛出异常的部分而被执行的函数,并且在catch
块内没有用。我已经阅读了http://en.cppreference.com/w/cpp/error,但似乎找不到任何适用的机制。#include <stdexcept>
#include <iostream>
struct foo {
// prints "dtor : 1"
~foo() { std::cout << "dtor : " << std::uncaught_exception() << std::endl; }
};
int main()
{
try
{
foo bar;
throw std::runtime_error("error");
}
catch (const std::runtime_error&)
{
// prints "catch : 0", I need a mechanism that would print 1
std::cout << "catch : " << std::uncaught_exception() << std::endl;
}
return 0;
}
我发现的变通办法包括简单地实现从
catch
块调用的其他函数,但是该解决方案将无法追溯。另一个方法是将thread_local
标志与自定义异常类一起使用,以了解当前线程何时构造了异常但并未销毁它,但这似乎容易出错,并且与标准和现有异常类不兼容。此弱解决方法的示例:#include <exception>
struct my_base_except : public std::exception
{
my_base_except() { ++error_count; }
virtual ~my_base_except() { --error_count; }
my_base_except(const my_base_except &) { ++error_count; }
my_base_except(my_base_except&&) { ++error_count; }
static bool is_in_catch() {
return error_count > 0;
}
private:
static thread_local int error_count;
};
thread_local int my_base_except::error_count = 0;
void log_error()
{
if (my_base_except::is_in_catch())
{
// Proceed to rethrow and use the additional information
}
else
{
// Proceed with the existing implementation
}
}
是否存在解决此问题的标准功能?如果没有,是否有比我在此处确定的解决方案更强大的解决方法?
最佳答案
std::current_exception可能就是您想要的。std::current_exception
返回std::exception_ptr
,它是当前处理的异常的指针类型,或者nullptr
(如果未处理任何异常)。可以使用 std::rethrow_exception
重新抛出该异常。