做五金建材市场的网站,wordpress英文别名,直通车代运营,天河建设网站外包目录
1.自定义异常类spdlog_ex
1.1.通用异常
1.2.系统调用异常
1.3.what()函数
2.异常的使用
2.1.抛出异常
2.2.控制异常使用 1.自定义异常类spdlog_ex
标准库异常类#xff08;std::exception#xff09;系列#xff0c;能满足大多数使用异常的场景#xff0c;但对…目录
1.自定义异常类spdlog_ex
1.1.通用异常
1.2.系统调用异常
1.3.what()函数
2.异常的使用
2.1.抛出异常
2.2.控制异常使用 1.自定义异常类spdlog_ex
标准库异常类std::exception系列能满足大多数使用异常的场景但对系统调用异常及错误信息缺乏支持。spdlog通过继承std::exception扩展对系统调用的支持实现自定义异常类spdlog_ex。
spdlog_ex类声明很简单在std::exception基础上添加了string类型的msg_成员提供支持errno的构造函数。
// include/spdlog/details/common.h// Log exception
class SPDLOG_API spdlog_ex : public std::exception
{
public:explicit spdlog_ex(std::string msg);spdlog_ex(const std::string msg, int last_errno); // 提供系统调用错误号errno的支持const char *what() const SPDLOG_NOEXCEPT override;
private:std::string msg_; // 异常文本信息
};
1.1.通用异常
对于通用的异常spdlog_ex并未做什么特别的事情只是将用户传入的异常提示信息存放到msg_。
SPDLOG_INLINE spdlog_ex::spdlog_ex(std::string msg): msg_(std::move(msg))
{}
1.2.系统调用异常
spdlog_ex对errno的支持主要是将errno转换为对应错误文本信息存放到msg_字符串中。spdlog使用的是ftm库提供的format_system_error来完成转换工作出于对memory_buf_t支持。当然也可以使用C库函数strerror或者线程安全版本strerror_r。
SPDLOG_INLINE spdlog_ex::spdlog_ex(const std::string msg, int last_errno)
{
#ifdef SPDLOG_USE_STD_FORMATmsg_ std::system_error(std::error_code(last_errno, std::generic_category()), msg).what();
#elsememory_buf_t outbuf;fmt::format_system_error(outbuf, last_errno, msg.c_str());msg_ fmt::to_string(outbuf);
#endif
}
1.3.what()函数
what()是基类std::exception定义的virtual函数用户通常通过该接口获取异常信息。spdlog_ex也是简单的返回存放异常信息的msg_。
SPDLOG_INLINE const char *spdlog_ex::what() const SPDLOG_NOEXCEPT
{return msg_.c_str();
}
2.异常的使用
2.1.抛出异常
前面是讲如何实现spdlog_ex但如何在spdlog中抛出一个异常对象呢直接调用throw spdlog_ex(..) spdlog提供了重载函数形式的接口throw_spdlog_ex。
SPDLOG_INLINE void throw_spdlog_ex(const std::string msg, int last_errno)
{SPDLOG_THROW(spdlog_ex(msg, last_errno));
}SPDLOG_INLINE void throw_spdlog_ex(std::string msg)
{SPDLOG_THROW(spdlog_ex(std::move(msg)));
}
throw_spdlog_ex本质上也是throw spdlog_ex(..)为何要通过一个宏定义SPDLOG_THROW来进行呢 这就涉及到下面要讲的控制异常使用。
2.2.控制异常使用
有些APP并不希望第三方库抛出异常而有些无所谓。为此spdlog提供两种模式抛出异常不抛出异常通过宏定义SPDLOG_NO_EXCEPTIONS来控制。 当没有定义宏SPDLOG_NO_EXCEPTIONS时正常抛出异常对象 当定义了宏SPDLOG_NO_EXCEPTIONS时抛出异常替换为直接终止程序abort
#ifdef SPDLOG_NO_EXCEPTIONS
# define SPDLOG_TRY
# define SPDLOG_THROW(ex) \do \{ \printf(spdlog fatal error: %s\n, ex.what()); \std::abort(); \} while (0)
# define SPDLOG_CATCH_STD
#else
# define SPDLOG_TRY try
# define SPDLOG_THROW(ex) throw(ex)
# define SPDLOG_CATCH_STD \catch (const std::exception ) {}
#endif
通过这种方式spdlog异常处理更加灵活更好适配APP对是否抛出异常的需求。
因此在spdlog中捕获异常的代码块try-catch看起来会是这样
// message all threads to terminate gracefully join them
SPDLOG_INLINE thread_pool::~thread_pool()
{SPDLOG_TRY{for (size_t i 0; i threads_.size(); i){post_async_msg_(async_msg(async_msg_type::terminate), async_overflow_policy::block);}for (auto t : threads_){t.join();}}SPDLOG_CATCH_STD
}
当然也可以使用自定义捕获catch代码块替换SPDLOG_CATCH_STD看起来会是这样
SPDLOG_INLINE void spdlog::async_logger::backend_flush_()
{for (auto sink : sinks_){SPDLOG_TRY{sink-flush();}SPDLOG_LOGGER_CATCH(source_loc())}
}#ifndef SPDLOG_NO_EXCEPTIONS
# define SPDLOG_LOGGER_CATCH(location) \catch (const std::exception ex) \{ \if (location.filename) \{ \err_handler_(fmt_lib::format(SPDLOG_FMT_STRING({} [{}({})]), ex.what(), location.filename, location.line)); \} \else \{ \err_handler_(ex.what()); \} \} \catch (...) \{ \err_handler_(Rethrowing unknown exception in logger); \throw; \}
#else
# define SPDLOG_LOGGER_CATCH(location)
#endif