当前位置: 首页 > news >正文

spdlog日志库源码:自定义异常类spdlog_ex

自定义异常类spdlog_ex

标准库异常类(std::exception)系列,能满足大多数使用异常的场景,但对系统调用异常及错误信息缺乏支持。spdlog通过继承std::exception,扩展对系统调用的支持,实现自定义异常类spdlog_ex。

spdlog_ex类声明只是在std::exception基础上添加了string类型的msg_成员,提供支持errno的构造函数。

// include/spdlog/common.h
class SPDLOG_API spdlog_ex : public std::exception {
public:explicit spdlog_ex(std::string msg);spdlog_ex(const std::string &msg, int last_errno);const char *what() const SPDLOG_NOEXCEPT override;private:std::string msg_;
};

异常

SPDLOG_INLINE spdlog_ex::spdlog_ex(std::string msg): msg_(std::move(msg)) {}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

对于通用的异常,spdlog_ex只是将用户传入的异常提示信息存放到msg_。

spdlog_ex对errno的支持,主要是将errno转换为对应错误文本信息,存放到msg_字符串中。spdlog使用的是ftm库提供的format_system_error来完成转换工作。

what()函数

SPDLOG_INLINE const char *spdlog_ex::what() const SPDLOG_NOEXCEPT {return msg_.c_str(); 
}

what()是基类std::exception定义的virtual函数,用户通常通过该接口获取异常信息。spdlog_ex返回存放异常信息的msg_。

异常的使用

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

抛出异常可以是这样:

// send flush request to the thread pool
SPDLOG_INLINE void spdlog::async_logger::flush_(){SPDLOG_TRY{auto pool_ptr = thread_pool_.lock();if (!pool_ptr) {throw_spdlog_ex("async flush: thread pool doesn't exist anymore");}std::future<void> future = pool_ptr->post_flush(shared_from_this(), overflow_policy_);future.get();}SPDLOG_LOGGER_CATCH(source_loc())
}

throw_spdlog_ex本质上也是throw spdlog_ex(…),这里多了宏定义SPDLOG_THROW。

#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_NO_EXCEPTIONS时,正常抛出异常对象;
  • 当定义了宏SPDLOG_NO_EXCEPTIONS时,抛出异常替换为直接终止程序(abort)

因此,在spdlog中,捕获异常的代码块try-catch,看起来会是这样:

SPDLOG_INLINE thread_pool::~thread_pool()
{// 析构函数不要抛出异常, 但释放线程池资源资源可能发生异常, 因此内部捕获并处理SPDLOG_TRY{for (size_t i = 0; i < threads_.size(); i++) {// 有几个子线程,就要post几个terminate的async_msg。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

catch (const std::exception &ex):捕获所有从 std::exception 派生的异常。

if (location.filename):如果提供了源代码位置信息(文件名),则格式化错误消息,包括异常的 what() 信息和源代码位置。

err_handler_:这是一个错误处理函数或对象,用于处理和记录错误消息。

catch (…):捕获所有其他类型的异常。

err_handler_(“Rethrowing unknown exception in logger”):记录一个未知异常的错误消息。

throw:重新抛出捕获的异常。

如果禁用了异常处理(通过定义 SPDLOG_NO_EXCEPTIONS),这个宏展开为空。

相关文章:

spdlog日志库源码:自定义异常类spdlog_ex

自定义异常类spdlog_ex 标准库异常类&#xff08;std::exception&#xff09;系列&#xff0c;能满足大多数使用异常的场景&#xff0c;但对系统调用异常及错误信息缺乏支持。spdlog通过继承std::exception&#xff0c;扩展对系统调用的支持&#xff0c;实现自定义异常类spdlo…...

3.每日LeetCode-数组类,爬楼梯(Go,Java,Python)

目录 题目 解法 Go Java Python 代码地址&#xff1a;leetcode: 每日leetcode刷题 题目 题号70. 爬楼梯 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 示例 1&#xff1a; 输入&#xff…...

单节点11.2.0.3参数文件恢复到RAC11.2.0.4启动失败

问题描述 通过pfile生成spfile失败&#xff0c;提示DATA磁盘不存在 SQL> create spfileDATA/DXJ/spfiledxj.ora from pfile/home/oracle/initdxj20240529.ora; create spfileDATA/DXJ/spfiledxj.ora from pfile/home/oracle/initdxj20240529.ora * ERROR at line 1: ORA-1…...

Windows电脑高颜值桌面便利贴,便签怎么设置

在这个看颜值的时代&#xff0c;我们不仅在衣着打扮上追求时尚与美观&#xff0c;就连电脑桌面也不愿放过。一张唯美的壁纸&#xff0c;几款别致的小工具&#xff0c;总能让我们的工作空间焕发出不一样的光彩。如果你也热衷于打造高颜值的电脑桌面&#xff0c;那么&#xff0c;…...

代码随想录35期Day54-Java

Day54题目 LeetCode392判断子序列 核心思想:公共子序列长度达到需要判断的字符串的长度,说明是子序列 class Solution {public boolean isSubsequence(String s, String t) {if("".equals(s)) return true;int[][] dp new int[s.length()1][t.length()1];for(int…...

Ubuntu使用sudo命令

在Ubuntu系统中&#xff0c;使用管理员权限通常涉及到使用sudo命令。这是因为Ubuntu默认情况下不直接允许root用户登录&#xff0c;而是通过sudo命令来执行需要管理员权限的任务。以下是一些常见的使用管理员权限的方法&#xff1a; 1. 使用sudo命令 运行单个命令 如果只需要…...

三方语言中调用, Go Energy GUI编译的dll动态链接库CEF

如何在其它编程语言中调用energy编译的dll动态链接库&#xff0c;以使用CEF 或 LCL库 Energy是Go语言基于LCL CEF开发的跨平台GUI框架, 具有很容易使用CEF 和 LCL控件库 interface 便利 示例链接 正文 为方便起见使用 python 调用 go energy 编译的dll 准备 系统&#x…...

Go微服务: Grpc服务注册在Consul的示例(非Go-Micro)

概述 现在&#xff0c;我们使用consul客户端的api来把GRPC服务实现注册到consul上&#xff0c;非Go-Micro的形式其实&#xff0c;consul官方提供了对应的接口调用来实现&#xff0c;golang中的consul/api包对其进行了封装我们使用consul/api来进行展示 目录结构 gitee.com/g…...

Java+Swing+Mysql实现飞机订票系统

一、系统介绍 1.开发环境 操作系统&#xff1a;Win10 开发工具 &#xff1a;Eclipse2021 JDK版本&#xff1a;jdk1.8 数据库&#xff1a;Mysql8.0 2.技术选型 JavaSwingMysql 3.功能模块 4.数据库设计 1.用户表&#xff08;users&#xff09; 字段名称 类型 记录内容…...

2024 rk

1.mysql、redis分布式锁 case: 商品秒杀 1)使用 MySQL 作为分布式锁来实现商品秒杀功能可能存在以下几个缺点&#xff1b; 使用 MySQL 作为分布式锁来实现商品秒杀功能可能存在以下几个缺点&#xff1a; 单点故障&#xff1a;如果使用单个 MySQL 实例作为分布式锁的存储介质…...

Java实现多张图片合并保存到pdf中

Java实现多张图片合并保存到pdf中 1、依赖–maven <dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>2.0.24</version></dependency>2、上代码 package com.hxlinks.hxiot.contro…...

揭秘智慧校园:可视化技术引领教育新篇章

随着科技的飞速发展&#xff0c;我们的生活方式正在经历一场前所未有的变革。而在这场变革中&#xff0c;学校作为培养未来人才的重要基地&#xff0c;也在不断地探索与创新。 一、什么是校园可视化&#xff1f; 校园可视化&#xff0c;就是通过先进的信息技术&#xff0c;将学…...

基础9 探索图形化编程的奥秘:从物联网到工业自动化

办公室内&#xff0c;明媚的阳光透过窗户洒落&#xff0c;为每张办公桌披上了一层金色的光辉。同事们各自忙碌着&#xff0c;键盘敲击声、文件翻页声和低声讨论交织在一起&#xff0c;营造出一种忙碌而有序的氛围。空气中氤氲着淡淡的咖啡香气和纸张的清新味道&#xff0c;令人…...

RPC-----RCF

RPC RPC(Remote Procedure Call Protocol&#xff09;——远程过程调用协议。 RCF...

StarRocks中,这些配置项是表属性的一部分

CREATE TABLE warehouse.ads_order_all_df ( so_id varchar(200) NULL COMMENT "销售订单主表标识", so_code varchar(200) NULL COMMENT "销售订单主表表号" ) ENGINEOLAP DUPLICATE KEY(so_id) COMMENT "OLAP" DISTRIBUTED BY HASH(dt) …...

Activity->Activity生命周期

<四大组件 android:name"xxx"android:exported"true" // 该组边能够被其他组件启动android:enabled"true" // 该组件能工与用户交互 </四大组件>Activity常用生命周期 启动Activity 2024-05-29 03:53:57.401 21372-21372 yang …...

乐鑫ESP串口驱动安装,安装cp210x驱动

windows11安装cp210x驱动&#xff1a; 1&#xff1a;第一步官网下载驱动&#xff1a; 官网地址如下&#xff1a; CP210x USB to UART Bridge VCP Drivers - Silicon Labs 第二步&#xff1a;解压文件夹并安装如图所示&#xff1a; 3&#xff1a;第三步安装成功后会给你个提示…...

Django缓存

由于Django是动态网站&#xff0c;所有每次请求均会去数据进行相应的操作&#xff0c;当程序访问量大时&#xff0c;耗时必然会更加明显&#xff0c;最简单解决方式是使用&#xff1a;缓存&#xff0c;缓存将一个某个views的返回值保存至内存或者memcache中&#xff0c;若某个时…...

Python 元组

&#xff08;1&#xff09;元组中只包含一个元素时&#xff0c;需要在元素后面添加逗号&#xff1a; tup1 (50,); &#xff08;2&#xff09;元组中的元素值是不允许修改的&#xff0c;但我们可以对元组进行连接组合&#xff1a; tup1 (12, 34.56); tup2 (abc, xyz);# 以…...

JAVA面试题大全(十八)

1、说一下 jvm 的主要组成部分&#xff1f;及其作用&#xff1f; 类加载器&#xff08;ClassLoader&#xff09;运行时数据区&#xff08;Runtime Data Area&#xff09;执行引擎&#xff08;Execution Engine&#xff09;本地库接口&#xff08;Native Interface&#xff09;…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术&#xff0c;说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号&#xff08;调制&#xff09; 把信息从信号中抽取出来&am…...

spring:实例工厂方法获取bean

spring处理使用静态工厂方法获取bean实例&#xff0c;也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下&#xff1a; 定义实例工厂类&#xff08;Java代码&#xff09;&#xff0c;定义实例工厂&#xff08;xml&#xff09;&#xff0c;定义调用实例工厂&#xff…...

selenium学习实战【Python爬虫】

selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...

【Go语言基础【12】】指针:声明、取地址、解引用

文章目录 零、概述&#xff1a;指针 vs. 引用&#xff08;类比其他语言&#xff09;一、指针基础概念二、指针声明与初始化三、指针操作符1. &&#xff1a;取地址&#xff08;拿到内存地址&#xff09;2. *&#xff1a;解引用&#xff08;拿到值&#xff09; 四、空指针&am…...

claude3.7高阶玩法,生成系统架构图,国内直接使用

文章目录 零、前言一、操作指南操作指导 二、提示词模板三、实战图书管理系统通过4o模型生成系统描述通过claude3.7生成系统架构图svg代码转换成图片 在线考试系统通过4o模型生成系统描述通过claude3.7生成系统架构图svg代码转换成图片 四、感受 零、前言 现在很多AI大模型可以…...

Three.js进阶之粒子系统(一)

一些特定模糊现象&#xff0c;经常使用粒子系统模拟&#xff0c;如火焰、爆炸等。Three.js提供了多种粒子系统&#xff0c;下面介绍粒子系统 一、Sprite粒子系统 使用场景&#xff1a;下雨、下雪、烟花 ce使用代码&#xff1a; var materialnew THRESS.SpriteMaterial();//…...

奈飞工厂官网,国内Netflix影视在线看|中文网页电脑版入口

奈飞工厂是一个专注于提供免费Netflix影视资源的在线播放平台&#xff0c;致力于为国内用户提供的Netflix热门影视内容。该平台的资源与Netflix官网基本同步&#xff0c;涵盖电影、电视剧、动漫和综艺等多个领域。奈飞工厂的界面简洁流畅&#xff0c;资源分类清晰&#xff0c;方…...

用 DeepSeek 高效完成数据分析与挖掘

一、DeepSeek 是什么? DeepSeek 是由深度求索推出的智能助手(当前版本 DeepSeek-R1),具备强大的自然语言理解、代码生成与数据分析能力。它支持 128K超长上下文,可处理复杂数据文档,并直接生成可运行的 Python 数据分析代码,是数据工作者的“AI副驾驶”。 二、DeepSeek…...